Nette Documentation Preview

syntax
Sesje
*****

<div class=perex>

HTTP jest protokołem bezstanowym, ale prawie każda aplikacja musi przechowywać stan między żądaniami, takimi jak zawartość koszyka na zakupy. Po to właśnie jest sesja. Zobaczmy,

- jak korzystać z sesji
- jak uniknąć konfliktów nazw
- jak ustawić wygaśnięcie

</div>

W przypadku korzystania z sesji, każdy użytkownik otrzymuje unikalny identyfikator zwany identyfikatorem sesji, który jest przekazywany w pliku cookie. Służy to jako klucz do danych sesji. W przeciwieństwie do plików cookie, które są przechowywane po stronie przeglądarki, dane sesyjne są przechowywane po stronie serwera.

Sesję ustawiamy w [konfiguracji |configuration#Session], szczególnie ważny jest wybór czasu wygaśnięcia.

Zarządzanie sesją jest obsługiwane przez obiekt [api:Nette\Http\Session], do którego uzyskujesz dostęp poprzez przekazanie go za pomocą [zastrzyku zależności |dependency-injection:passing-dependencies]. W presenterech wystarczy zadzwonić na `$session = $this->getSession()`.

→ [Instalacja i wymagania |@home#Installation]


Rozpoczęcie sesji .[#toc-starting-session]
==========================================

Domyślnie Nette rozpoczyna sesję automatycznie w momencie, gdy zaczniemy z niej czytać lub zapisywać do niej dane. Aby ręcznie rozpocząć sesję, użyj `$session->start()`.

PHP wysyła nagłówki HTTP wpływające na buforowanie, gdy sesja jest uruchamiana, zobacz [php:session_cache_limiter], i ewentualnie plik cookie z identyfikatorem sesji. Dlatego zawsze musisz rozpocząć sesję przed wysłaniem jakiegokolwiek wyjścia do przeglądarki, w przeciwnym razie zostanie rzucony wyjątek. Więc jeśli wiesz, że sesja będzie używana podczas renderowania strony, uruchom ją ręcznie wcześniej, być może w prezenterze.

W trybie deweloperskim Tracy uruchamia sesję, ponieważ używa jej do wyświetlania pasków przekierowań i żądań AJAX w pasku Tracy.


Sekcja .[#toc-section]
======================

W czystym PHP, magazyn danych sesji jest zaimplementowany jako tablica dostępna poprzez zmienną globalną `$_SESSION`. Problem polega na tym, że aplikacje zwykle składają się z wielu niezależnych części, a jeśli wszystkie z nich mają tylko jedno dostępne pole, prędzej czy później nazwy będą kolidować.

Nette Framework rozwiązuje ten problem dzieląc całą przestrzeń na sekcje ( [api:Nette\Http\SessionSection] obiekty ). Każda jednostka korzysta wtedy z własnej sekcji o unikalnej nazwie i nie może już dojść do żadnych kolizji.

Odcinek jest pozyskiwany z sesji:

```php
$section = $session->getSection('unikatni nazev');
```

W prezenterze wystarczy użyć `getSession()` z parametrem:

```php
// $this jest prezenterem
$section = $this->getSession('unikatni nazev');
```

Aby sprawdzić istnienie odcinka, należy użyć metody `$session->hasSection('unikatni nazev')`.

Sama sekcja jest następnie bardzo łatwa do pracy z wykorzystaniem metod `set()`, `get()` i `remove()`:

```php
// pisanie zmiennych
$section->set('userName', 'franta');

// odczytuje zmienną, zwraca null jeśli nie istnieje
echo $section->get('userName');

// anulowanie zmiennej
$section->remove('userName');
```

Możesz użyć pętli `foreach`, aby uzyskać wszystkie zmienne z sekcji:

```php
foreach ($section as $key => $val) {
	echo "$key = $val";
}
```


Ustawienia wygaśnięcia .[#toc-how-to-set-expiration]
----------------------------------------------------

Możliwe jest ustawienie wygasania dla poszczególnych sekcji lub nawet poszczególnych zmiennych. W ten sposób możemy pozwolić, aby login użytkownika wygasł za 20 minut, ale nadal pamiętał zawartość koszyka.

```php
// sekcja wygasa po 20 minutach
$section->setExpiration('20 minutes');
```

Trzeci parametr metody `set()` służy do ustawienia wygasania poszczególnych zmiennych:

```php
// zmienna 'flash' wygasa po 30 sekundach
$section->set('flash', $message, '30 sekund');
```

.[note]
Pamiętaj, że czas wygaśnięcia całej sesji (patrz [konfiguracja |configuration#Session] sesji) musi być równy lub wyższy niż czas wygaśnięcia ustawiony dla poszczególnych sekcji lub zmiennych.

Anulowanie wcześniej ustawionego wygaśnięcia uzyskuje się za pomocą metody `removeExpiration()` Metoda `remove()` zapewnia natychmiastowe anulowanie całego odcinka.


Zdarzenia $onStart, $onBeforeWrite .[#toc-events-onstart-onbeforewrite]
-----------------------------------------------------------------------

Obiekt `Nette\Http\Session` posiada [zdarzenia |nette:glossary#Events] `$onStart` i `$onBeforeWrite`, więc można dodać wywołania zwrotne, które odpalają się po rozpoczęciu sesji lub przed jej zapisaniem na dysk, a następnie zakończeniem.

```php
$session->onBeforeWrite[] = function () {
	// zapiszemy dane do sesji
	$this->section->set('basket', $this->basket);
};
```


Zarządzanie sesją .[#toc-session-management]
============================================

Przegląd metod klasy `Nette\Http\Session` służących do zarządzania sesjami:

<div class=wiki-methods-brief>


start(): void .[method]
-----------------------
Otworzy on sesję.


isStarted(): bool .[method]
---------------------------
Czy sesja została rozpoczęta?


close(): void .[method]
-----------------------
Kończy sesję. Sesja jest automatycznie kończona po zakończeniu działania skryptu.


destroy(): void .[method]
-------------------------
Kończy i usuwa sesję.


exists(): bool .[method]
------------------------
Czy żądanie HTTP zawiera plik cookie z identyfikatorem sesji?


regenerateId(): void .[method]
------------------------------
Generuje nowy losowy identyfikator sesji. Dane są zachowane.


getId(): string .[method]
-------------------------
Zwraca identyfikator sesji.

</div>


Konfiguracja .[#toc-configuration]
----------------------------------

Sesja jest ustawiona w [konfiguracji |configuration#Session]. Jeśli piszesz aplikację, która nie korzysta z kontenera DI, do jej konfiguracji służą następujące metody. Muszą one zostać wywołane przed rozpoczęciem sesji.

<div class=wiki-methods-brief>


setName(string $name): static .[method]
---------------------------------------
Ustawia nazwę pliku cookie, w którym przekazywany jest identyfikator sesji. Domyślna nazwa to `PHPSESSID`. Jest to przydatne, jeśli w ramach tej samej witryny uruchamiasz kilka różnych aplikacji.


getName(): string .[method]
---------------------------
Zwraca nazwę pliku cookie, w którym przekazywany jest identyfikator sesji.


setOptions(array $options): static .[method]
--------------------------------------------
Konfiguruje sesję. Można ustawić wszystkie [dyrektywy |https://www.php.net/manual/en/session.configuration.php] sesji PHP (w formacie camelCase, np. zamiast `session.save_path` wpisz `savePath`), a także [readAndClose |https://www.php.net/manual/en/function.session-start.php#refsect1-function.session-start-parameters].


setExpiration(?string $time): static .[method]
----------------------------------------------
Ustawia okres bezczynności, po którym sesja wygasa.


setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static .[method]
------------------------------------------------------------------------------------------------------------------
Ustawia parametry dla pliku cookie. Można zmienić domyślne wartości parametrów w [konfiguracji |configuration#Session-Cookie].


setSavePath(string $path): static .[method]
-------------------------------------------
Ustawia katalog, w którym przechowywane są pliki sesji.


setHandler(\SessionHandlerInterface $handler): static .[method]
---------------------------------------------------------------
Ustaw niestandardowy handler, zobacz [dokumentację PHP |https://www.php.net/manual/en/class.sessionhandlerinterface.php].

</div>


W szczególności bezpieczeństwo .[#toc-safety-first]
===================================================

Serwer zakłada, że wciąż komunikuje się z tym samym użytkownikiem, dopóki żądaniom towarzyszy ten sam identyfikator sesji. Zadaniem mechanizmów bezpieczeństwa jest zapewnienie, że tak rzeczywiście jest i że identyfikator sesji nie może zostać skradziony lub sfałszowany.

Dlatego Nette Framework odpowiednio konfiguruje dyrektywy PHP, aby przekazywały identyfikator sesji tylko w ciasteczku, czyniły go niedostępnym dla JavaScript i ignorowały wszelkie identyfikatory w URL. Ponadto w krytycznych momentach, takich jak logowanie się użytkownika, wygeneruje nowy identyfikator sesji.

Do konfiguracji PHP służy funkcja ini_set, która niestety jest wyłączona przez niektóre hosty. Jeśli tak jest również w przypadku twojego hosta, spróbuj porozmawiać z nimi, aby włączyć tę funkcję lub przynajmniej skonfigurować serwer dla ciebie. .[note]

Sesje

HTTP jest protokołem bezstanowym, ale prawie każda aplikacja musi przechowywać stan między żądaniami, takimi jak zawartość koszyka na zakupy. Po to właśnie jest sesja. Zobaczmy,

  • jak korzystać z sesji
  • jak uniknąć konfliktów nazw
  • jak ustawić wygaśnięcie

W przypadku korzystania z sesji, każdy użytkownik otrzymuje unikalny identyfikator zwany identyfikatorem sesji, który jest przekazywany w pliku cookie. Służy to jako klucz do danych sesji. W przeciwieństwie do plików cookie, które są przechowywane po stronie przeglądarki, dane sesyjne są przechowywane po stronie serwera.

Sesję ustawiamy w konfiguracji, szczególnie ważny jest wybór czasu wygaśnięcia.

Zarządzanie sesją jest obsługiwane przez obiekt Nette\Http\Session, do którego uzyskujesz dostęp poprzez przekazanie go za pomocą zastrzyku zależności. W presenterech wystarczy zadzwonić na $session = $this->getSession().

Instalacja i wymagania

Rozpoczęcie sesji

Domyślnie Nette rozpoczyna sesję automatycznie w momencie, gdy zaczniemy z niej czytać lub zapisywać do niej dane. Aby ręcznie rozpocząć sesję, użyj $session->start().

PHP wysyła nagłówki HTTP wpływające na buforowanie, gdy sesja jest uruchamiana, zobacz session_cache_limiter, i ewentualnie plik cookie z identyfikatorem sesji. Dlatego zawsze musisz rozpocząć sesję przed wysłaniem jakiegokolwiek wyjścia do przeglądarki, w przeciwnym razie zostanie rzucony wyjątek. Więc jeśli wiesz, że sesja będzie używana podczas renderowania strony, uruchom ją ręcznie wcześniej, być może w prezenterze.

W trybie deweloperskim Tracy uruchamia sesję, ponieważ używa jej do wyświetlania pasków przekierowań i żądań AJAX w pasku Tracy.

Sekcja

W czystym PHP, magazyn danych sesji jest zaimplementowany jako tablica dostępna poprzez zmienną globalną $_SESSION. Problem polega na tym, że aplikacje zwykle składają się z wielu niezależnych części, a jeśli wszystkie z nich mają tylko jedno dostępne pole, prędzej czy później nazwy będą kolidować.

Nette Framework rozwiązuje ten problem dzieląc całą przestrzeń na sekcje ( Nette\Http\SessionSection obiekty ). Każda jednostka korzysta wtedy z własnej sekcji o unikalnej nazwie i nie może już dojść do żadnych kolizji.

Odcinek jest pozyskiwany z sesji:

$section = $session->getSection('unikatni nazev');

W prezenterze wystarczy użyć getSession() z parametrem:

// $this jest prezenterem
$section = $this->getSession('unikatni nazev');

Aby sprawdzić istnienie odcinka, należy użyć metody $session->hasSection('unikatni nazev').

Sama sekcja jest następnie bardzo łatwa do pracy z wykorzystaniem metod set(), get() i remove():

// pisanie zmiennych
$section->set('userName', 'franta');

// odczytuje zmienną, zwraca null jeśli nie istnieje
echo $section->get('userName');

// anulowanie zmiennej
$section->remove('userName');

Możesz użyć pętli foreach, aby uzyskać wszystkie zmienne z sekcji:

foreach ($section as $key => $val) {
	echo "$key = $val";
}

Ustawienia wygaśnięcia

Możliwe jest ustawienie wygasania dla poszczególnych sekcji lub nawet poszczególnych zmiennych. W ten sposób możemy pozwolić, aby login użytkownika wygasł za 20 minut, ale nadal pamiętał zawartość koszyka.

// sekcja wygasa po 20 minutach
$section->setExpiration('20 minutes');

Trzeci parametr metody set() służy do ustawienia wygasania poszczególnych zmiennych:

// zmienna 'flash' wygasa po 30 sekundach
$section->set('flash', $message, '30 sekund');

Pamiętaj, że czas wygaśnięcia całej sesji (patrz konfiguracja sesji) musi być równy lub wyższy niż czas wygaśnięcia ustawiony dla poszczególnych sekcji lub zmiennych.

Anulowanie wcześniej ustawionego wygaśnięcia uzyskuje się za pomocą metody removeExpiration() Metoda remove() zapewnia natychmiastowe anulowanie całego odcinka.

Zdarzenia $onStart, $onBeforeWrite

Obiekt Nette\Http\Session posiada zdarzenia $onStart i $onBeforeWrite, więc można dodać wywołania zwrotne, które odpalają się po rozpoczęciu sesji lub przed jej zapisaniem na dysk, a następnie zakończeniem.

$session->onBeforeWrite[] = function () {
	// zapiszemy dane do sesji
	$this->section->set('basket', $this->basket);
};

Zarządzanie sesją

Przegląd metod klasy Nette\Http\Session służących do zarządzania sesjami:

start(): void

Otworzy on sesję.

isStarted(): bool

Czy sesja została rozpoczęta?

close(): void

Kończy sesję. Sesja jest automatycznie kończona po zakończeniu działania skryptu.

destroy(): void

Kończy i usuwa sesję.

exists(): bool

Czy żądanie HTTP zawiera plik cookie z identyfikatorem sesji?

regenerateId(): void

Generuje nowy losowy identyfikator sesji. Dane są zachowane.

getId(): string

Zwraca identyfikator sesji.

Konfiguracja

Sesja jest ustawiona w konfiguracji. Jeśli piszesz aplikację, która nie korzysta z kontenera DI, do jej konfiguracji służą następujące metody. Muszą one zostać wywołane przed rozpoczęciem sesji.

setName(string $name): static

Ustawia nazwę pliku cookie, w którym przekazywany jest identyfikator sesji. Domyślna nazwa to PHPSESSID. Jest to przydatne, jeśli w ramach tej samej witryny uruchamiasz kilka różnych aplikacji.

getName(): string

Zwraca nazwę pliku cookie, w którym przekazywany jest identyfikator sesji.

setOptions(array $options)static

Konfiguruje sesję. Można ustawić wszystkie dyrektywy sesji PHP (w formacie camelCase, np. zamiast session.save_path wpisz savePath), a także readAndClose.

setExpiration(?string $time)static

Ustawia okres bezczynności, po którym sesja wygasa.

setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null)static

Ustawia parametry dla pliku cookie. Można zmienić domyślne wartości parametrów w konfiguracji.

setSavePath(string $path)static

Ustawia katalog, w którym przechowywane są pliki sesji.

setHandler(\SessionHandlerInterface $handler)static

Ustaw niestandardowy handler, zobacz dokumentację PHP.

W szczególności bezpieczeństwo

Serwer zakłada, że wciąż komunikuje się z tym samym użytkownikiem, dopóki żądaniom towarzyszy ten sam identyfikator sesji. Zadaniem mechanizmów bezpieczeństwa jest zapewnienie, że tak rzeczywiście jest i że identyfikator sesji nie może zostać skradziony lub sfałszowany.

Dlatego Nette Framework odpowiednio konfiguruje dyrektywy PHP, aby przekazywały identyfikator sesji tylko w ciasteczku, czyniły go niedostępnym dla JavaScript i ignorowały wszelkie identyfikatory w URL. Ponadto w krytycznych momentach, takich jak logowanie się użytkownika, wygeneruje nowy identyfikator sesji.

Do konfiguracji PHP służy funkcja ini_set, która niestety jest wyłączona przez niektóre hosty. Jeśli tak jest również w przypadku twojego hosta, spróbuj porozmawiać z nimi, aby włączyć tę funkcję lub przynajmniej skonfigurować serwer dla ciebie.