SafeStream: bezpiecznie do plików
Nette SafeStream gwarantuje, że każdy odczyt i zapis do pliku jest izolowany. Oznacza to, że żaden wątek nie rozpocznie czytania pliku, który nie jest jeszcze w pełni zapisany, lub wiele wątków nadpisze ten sam plik.
Instalacja:
composer require nette/safe-stream
Do czego się nadaje?
Do czego przydaje się izolowana chirurgia? Zacznijmy od prostego przykładu, który wielokrotnie zapisuje do pliku, a następnie odczytuje z niego ten sam ciąg znaków:
$s = str_repeat('Long String', 10000);
$counter = 1000;
while ($counter--) {
file_put_contents('soubor', $s); // zapisujemy
$readed = file_get_contents('soubor'); // czytaj
if ($s !== $readed) { // sprawdź to
echo 'řetězce se liší!'
}
}
Może się wydawać, że wezwanie na echo 'řetězce se liší!'
nigdy nie może mieć miejsca. Jest wręcz
przeciwnie. Spróbuj uruchomić ten skrypt w dwóch zakładkach przeglądarki jednocześnie. Błąd pojawi się niemal
natychmiast.
Jedna z zakładek odczyta plik, gdy druga zakładka nie zapisała jeszcze całego pliku, więc zawartość nie będzie kompletna.
Dlatego kod nie jest bezpieczny, jeśli jest wykonywany wielokrotnie w tym samym czasie (tj. W wielu wątkach). Co nie jest rzadkością w internecie, często serwer odpowiada na dużą liczbę użytkowników w jednym czasie. Tak więc zapewnienie, że twoja aplikacja działa niezawodnie nawet podczas wykonywania w wielu wątkach (thread-safe) jest bardzo ważne. W przeciwnym razie dane zostaną utracone i pojawią się trudne do wykrycia błędy.
Ale jak widać, natywne funkcje odczytu i zapisu plików w PHP nie są izolowane i atomowe.
Jak korzystać z SafeStream?
SafeStream tworzy bezpieczny protokół, który może być używany do odczytu i zapisu plików w izolacji przy użyciu
standardowych funkcji PHP. Wystarczy umieścić nette.safe://
przed nazwą pliku:
file_put_contents('nette.safe://soubor', $s);
$s = file_get_contents('nette.safe://soubor');
SafeStream zapewnia, że nie więcej niż jeden wątek może pisać do pliku w tym samym czasie. Pozostałe wątki ustawiają się w kolejce. Jeśli żaden wątek nie pisze, dowolna liczba wątków może czytać plik równolegle.
Wszystkie popularne funkcje PHP mogą być używane z protokołem, na przykład:
// 'r' oznacza otwarcie tylko do odczytu
$handle = fopen('nette.safe://file.txt', 'r');
$ini = parse_ini_file('nette.safe://translations.neon');