Praca z adresami URL
********************
.[perex]
Klasy [#Url], [#UrlImmutable] i [#UrlScript] ułatwiają generowanie, parsowanie i manipulowanie adresami URL.
→ [Instalacja i wymagania |@home#Instalacja]
Url
===
Klasa [api:Nette\Http\Url] pozwala łatwo manipulować adresami URL i ich poszczególnymi składowymi, jak pokazuje ten diagram:
/--pre
scheme user password host port path query fragment
| | | | | | | |
/--\ /--\ /------\ /-------\ /--\/----------\ /--------\ /----\
<b>http://john:xyz%2A12@nette.org:8080/en/download?name=param#footer</b>
\______\__________________________/
| |
hostUrl authority
\--
Generowanie URL-i jest intuicyjne:
```php
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 możesz też sparsować, a następnie nim manipulować:
```php
$url = new Url(
'http://john:xyz%2A12@nette.org:8080/en/download?name=param#footer',
);
```
Klasa `Url` implementuje interfejs `JsonSerializable` i ma metodę `__toString()`, więc obiekt można wypisać albo użyć w danych przekazywanych do `json_encode()`.
```php
echo $url;
echo json_encode([$url]);
```
Składowe URL
------------
Do odczytu albo zmiany poszczególnych składowych URL służą poniższe metody:
.[language-php]
| Setter | Getter | Zwracana wartość
|--------------------------------------------------------------------------------------------
| `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` | cały URL
Metody `getUser()`, `getPassword()`, `setUser()` i `setPassword()` są przestarzałe, bo osadzanie danych uwierzytelniających bezpośrednio w URL jest odradzane.
Uwaga: przy pracy z URL uzyskanym z [żądania HTTP |request] pamiętaj, że nie będzie zawierał fragmentu, bo przeglądarka nie wysyła go na serwer.
Z poszczególnymi parametrami query możemy pracować za pomocą:
.[language-php]
| Setter | Getter
|---------------------------------------------------
| `setQuery(string\|array $query)` | `getQueryParameters(): array`
| `setQueryParameter(string $name, $val)` | `getQueryParameter(string $name)`
| `appendQuery(string|array $query)` |
getDomain(int $level = 2): string .[method]
-------------------------------------------
Zwraca prawą albo lewą część hosta. Oto jak to działa, jeśli hostem jest `www.nette.org`:
.[language-php]
| `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 .[method]
----------------------------------------
Sprawdza, czy dwa URL-e są identyczne.
```php
$url->isEqual('https://nette.org');
```
canonicalize() .[method]
------------------------
Konwertuje URL do postaci kanonicznej. Zamienia nazwę hosta na małe litery i normalizuje ścieżkę (percent-encoding i usunięcie zbędnych znaków). Query string pozostaje niezmieniony.
Url::isAbsolute(string $url): bool .[method]{data-version:3.3.2}
----------------------------------------------------------------
Sprawdza, czy URL jest absolutny. URL uznaje się za absolutny, jeśli zaczyna się schematem (np. http, https, ftp), po którym następuje dwukropek.
```php
Url::isAbsolute('https://nette.org'); // true
Url::isAbsolute('//nette.org'); // false
```
Url::removeDotSegments(string $path): string .[method]{data-version:3.3.2}
--------------------------------------------------------------------------
Normalizuje ścieżkę URL, usuwając specjalne segmenty `.` i `..`. Metoda usuwa zbędne elementy ścieżki tak samo, jak robią to przeglądarki.
```php
Url::removeDotSegments('/path/../subtree/./file.txt'); // '/subtree/file.txt'
Url::removeDotSegments('/../foo/./bar'); // '/foo/bar'
Url::removeDotSegments('./today/../file.txt'); // 'file.txt'
```
UrlImmutable
============
Klasa [api:Nette\Http\UrlImmutable] to niezmienna alternatywa dla klasy [#Url] (podobnie jak `DateTimeImmutable` jest w PHP niezmienną alternatywą dla `DateTime`). Zamiast setterów ma "withery", które nie zmieniają obiektu, tylko zwracają nowe instancje ze zmienioną wartością:
```php
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'
```
Klasa `UrlImmutable` implementuje interfejs `JsonSerializable` i ma metodę `__toString()`, więc obiekt można wypisać albo użyć w danych przekazywanych do `json_encode()`.
```php
echo $url;
echo json_encode([$url]);
```
Składowe URL
------------
Do odczytu albo zmiany poszczególnych składowych URL służą poniższe metody:
.[language-php]
| Wither | Getter | Zwracana wartość
|--------------------------------------------------------------------------------------------
| `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` | cały URL
Metody `getUser()`, `getPassword()`, `withUser()`, `withPassword()` i `withoutUserInfo()` są przestarzałe, bo osadzanie danych uwierzytelniających bezpośrednio w URL jest odradzane.
Z poszczególnymi parametrami query możemy pracować za pomocą:
.[language-php]
| Wither | Getter
|-----------------------------------------------
| `withQuery(string\|array $query)` | `getQueryParameters(): array`
| `withQueryParameter(string $name, $val)` | `getQueryParameter(string $name)`
getDomain(int $level = 2): string .[method]
-------------------------------------------
Zwraca prawą albo lewą część hosta. Oto jak to działa, jeśli hostem jest `www.nette.org`:
.[language-php]
| `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 .[method]{data-version:3.3.2}
----------------------------------------------------------------------
Rozwiązuje absolutny URL tak samo, jak przeglądarka przetwarza odnośniki na stronie HTML:
- jeśli odnośnik jest absolutnym URL (zawiera schemat), używany jest bez zmian
- jeśli odnośnik zaczyna się od `//`, przejmowany jest tylko schemat z bieżącego URL
- jeśli odnośnik zaczyna się od `/`, tworzona jest absolutna ścieżka od korzenia domeny
- w pozostałych przypadkach URL składany jest względem bieżącej ścieżki
```php
$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 .[method]
----------------------------------------
Sprawdza, czy dwa URL-e są identyczne.
```php
$url->isEqual('https://nette.org');
```
UrlScript
=========
Klasa [api:Nette\Http\UrlScript] to potomek [#UrlImmutable] rozszerzający ją o kolejne wirtualne składowe URL, jak katalog główny projektu itd. Podobnie jak klasa nadrzędna jest obiektem niezmiennym.
Poniższy diagram pokazuje składowe, które UrlScript rozpoznaje:
/--pre
baseUrl basePath relativePath relativeUrl
| | | |
/---------------/-----\/--------\---------------------------\
<b>http://nette.org/admin/script.php/pathinfo/?name=param#footer</b>
\_______________/\________/
| |
scriptPath pathInfo
\--
- `baseUrl` to bazowy URL aplikacji wraz z domeną i częścią ścieżki do katalogu głównego aplikacji
- `basePath` to część ścieżki do katalogu głównego aplikacji
- `scriptPath` to ścieżka do bieżącego skryptu
- `relativePath` to nazwa skryptu (i ewentualnie kolejne segmenty ścieżki) względem `basePath`
- `relativeUrl` to cała część URL za `baseUrl` wraz z query stringiem i fragmentem
- `pathInfo` to dziś rzadko używana część URL za nazwą skryptu
Do odczytu tych części URL służą poniższe metody:
.[language-php]
| Getter | Zwracana wartość
|------------------------------------------------
| `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/'`
Obiektów `UrlScript` zwykle nie tworzymy bezpośrednio; zamiast tego zwraca go metoda [Nette\Http\Request::getUrl() |request] z już poprawnie ustawionymi składowymi dla bieżącego żądania HTTP.
Praca z adresami URL
Klasy Url, UrlImmutable i UrlScript ułatwiają generowanie, parsowanie i manipulowanie adresami URL.
→ Instalacja i wymagania
Url
Klasa Nette\Http\Url pozwala łatwo manipulować adresami
URL i ich poszczególnymi składowymi, jak pokazuje ten diagram:
scheme user password host port path query fragment
| | | | | | | |
/--\ /--\ /------\ /-------\ /--\/----------\ /--------\ /----\
http://john:xyz%2A12@nette.org:8080/en/download?name=param#footer
\______\__________________________/
| |
hostUrl authority
Generowanie URL-i jest intuicyjne:
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 możesz też sparsować, a następnie nim manipulować:
$url = new Url(
'http://john:xyz%2A12@nette.org:8080/en/download?name=param#footer',
);
Klasa Url implementuje interfejs JsonSerializable i ma metodę __toString(), więc
obiekt można wypisać albo użyć w danych przekazywanych do json_encode().
echo $url;
echo json_encode([$url]);
Składowe URL
Do odczytu albo zmiany poszczególnych składowych URL służą poniższe metody:
| Setter |
Getter |
Zwracana wartość |
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 |
cały URL |
Metody getUser(), getPassword(), setUser() i setPassword() są
przestarzałe, bo osadzanie danych uwierzytelniających bezpośrednio w URL jest odradzane.
Uwaga: przy pracy z URL uzyskanym z żądania HTTP pamiętaj, że nie
będzie zawierał fragmentu, bo przeglądarka nie wysyła go na serwer.
Z poszczególnymi parametrami query możemy pracować za pomocą:
| Setter |
Getter |
setQuery(string|array $query) |
getQueryParameters(): array |
setQueryParameter(string $name, $val) |
getQueryParameter(string $name) |
| `appendQuery(string |
array $query)` |
getDomain (int $level = 2): string
Zwraca prawą albo lewą część hosta. Oto jak to działa, jeśli hostem jest 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
Sprawdza, czy dwa URL-e są identyczne.
$url->isEqual('https://nette.org');
canonicalize()
Konwertuje URL do postaci kanonicznej. Zamienia nazwę hosta na małe litery i normalizuje ścieżkę (percent-encoding
i usunięcie zbędnych znaków). Query string pozostaje niezmieniony.
Url::isAbsolute (string
$url): bool
Sprawdza, czy URL jest absolutny. URL uznaje się za absolutny, jeśli zaczyna się schematem (np. http, https, ftp), po
którym następuje dwukropek.
Url::isAbsolute('https://nette.org'); // true
Url::isAbsolute('//nette.org'); // false
Url::removeDotSegments (string $path): string
Normalizuje ścieżkę URL, usuwając specjalne segmenty . i ... Metoda usuwa zbędne elementy
ścieżki tak samo, jak robią to przeglądarki.
Url::removeDotSegments('/path/../subtree/./file.txt'); // '/subtree/file.txt'
Url::removeDotSegments('/../foo/./bar'); // '/foo/bar'
Url::removeDotSegments('./today/../file.txt'); // 'file.txt'
UrlImmutable
Klasa Nette\Http\UrlImmutable to niezmienna
alternatywa dla klasy Url (podobnie jak DateTimeImmutable jest w PHP niezmienną alternatywą
dla DateTime). Zamiast setterów ma “withery”, które nie zmieniają obiektu, tylko zwracają nowe instancje ze
zmienioną wartością:
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'
Klasa UrlImmutable implementuje interfejs JsonSerializable i ma metodę __toString(),
więc obiekt można wypisać albo użyć w danych przekazywanych do json_encode().
echo $url;
echo json_encode([$url]);
Składowe URL
Do odczytu albo zmiany poszczególnych składowych URL służą poniższe metody:
| Wither |
Getter |
Zwracana wartość |
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 |
cały URL |
Metody getUser(), getPassword(), withUser(), withPassword() i
withoutUserInfo() są przestarzałe, bo osadzanie danych uwierzytelniających bezpośrednio w URL jest odradzane.
Z poszczególnymi parametrami query możemy pracować za pomocą:
| Wither |
Getter |
withQuery(string|array $query) |
getQueryParameters(): array |
withQueryParameter(string $name, $val) |
getQueryParameter(string $name) |
getDomain (int $level = 2): string
Zwraca prawą albo lewą część hosta. Oto jak to działa, jeśli hostem jest 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
Rozwiązuje absolutny URL tak samo, jak przeglądarka przetwarza odnośniki na stronie HTML:
- jeśli odnośnik jest absolutnym URL (zawiera schemat), używany jest bez zmian
- jeśli odnośnik zaczyna się od
//, przejmowany jest tylko schemat z bieżącego URL
- jeśli odnośnik zaczyna się od
/, tworzona jest absolutna ścieżka od korzenia domeny
- w pozostałych przypadkach URL składany jest względem bieżącej ścieżki
$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
Sprawdza, czy dwa URL-e są identyczne.
$url->isEqual('https://nette.org');
UrlScript
Klasa Nette\Http\UrlScript to potomek UrlImmutable rozszerzający ją o kolejne wirtualne składowe URL, jak katalog główny projektu
itd. Podobnie jak klasa nadrzędna jest obiektem niezmiennym.
Poniższy diagram pokazuje składowe, które UrlScript rozpoznaje:
baseUrl basePath relativePath relativeUrl
| | | |
/---------------/-----\/--------\---------------------------\
http://nette.org/admin/script.php/pathinfo/?name=param#footer
\_______________/\________/
| |
scriptPath pathInfo
baseUrl to bazowy URL aplikacji wraz z domeną i częścią ścieżki do katalogu głównego aplikacji
basePath to część ścieżki do katalogu głównego aplikacji
scriptPath to ścieżka do bieżącego skryptu
relativePath to nazwa skryptu (i ewentualnie kolejne segmenty ścieżki) względem basePath
relativeUrl to cała część URL za baseUrl wraz z query stringiem i fragmentem
pathInfo to dziś rzadko używana część URL za nazwą skryptu
Do odczytu tych części URL służą poniższe metody:
| Getter |
Zwracana wartość |
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/' |
Obiektów UrlScript zwykle nie tworzymy bezpośrednio; zamiast tego zwraca go metoda Nette\Http\Request::getUrl() z już poprawnie ustawionymi składowymi dla
bieżącego żądania HTTP.