This post comes from the first version of this blog.
Please send me an email if anything needs an update. Thanks!

Programując jedną ze stron internetowych natrafiłem na ciekawy problem. Podczas testowania niektórych funkcji chciałem szybko powtórzyć wysyłanie formularza, tak, aby za każdym razem został dodany do bazy danych nowy rekord testowy. Wypełniłem formularz, zatwierdziłem przyciskiem “dodaj” i voila. Potem kilka razy [F5] i [Enter], aby przeglądarka powtórzyła wysyłanie danych metodą POST. Nie byłoby w tym nic nadzwyczajnego, poza tym, że w pewnym momencie zadziałały zabezpieczenia skryptu przed nieautoryzowanym dostępem i zostałem wylogowany z serwisu bez żadnego wcześniejszego powiadomienia. Myślę sobie: “WTF?”. Ze względu na to, że jestem dosyć cierpliwy w takich sprawach [nie wyobrażam sobie życia niecierpliwego programisty ;]] powtórzyłem poprzednie kroki, za każdym razem z tym samym skutkiem. Klikając zbyt szybko na stronie po prostu traciłem dane sesji, cała tablica $_SESSION była pusta jak /dev/null. Wypadałoby w takim razie przejrzeć kod i ewentualnie zapytać Google, co o tym sądzi. Do rozwiązania problemu wystarczyło to pierwsze, jednak, żeby poznać przyczynę, należało sięgnąć po źródła zewnętrzne.

Rozwiązanie było dosyć proste, zmiany wymagał pierwszy i jedyny parametr funkcji session_regenerate_id(), który ustawiłem kiedyś na “true”, a że rozwiązania z kodu, który działa, kopiuje się zwykle do innych miejsc, tak i ten, dopóki działał, był używany. Jej prototyp wygląda następująco [według oficjalnego manuala języka PHP w linkach na dole artykułu]:

phpbool session_regenerate_id([bool $deleteOldSession = false])

Zmiana na “false”, będąca, nawiasem mówiąc, wartością domyślną tego parametru, rozwiązała problem. Pozostało tylko dowiedzieć się “why, PHP, why?”.

Przyczyna problemu była bardzo prosta, a wynikała z niewydolności mojego lokalnego serwera w przypadku tak szybko po sobie następujących żądań. Wartość “true” pierwszego parametru funkcji session_regenerate_id() powoduje usunięcie z dysku pliku tymczasowego z danymi sesji i utworzenie nowego, zawierającego te same dane, ale pod innym identyfikatorem. W przypadku, kiedy wartość zostanie ustawiona na “false”, funkcja zmieni tylko identyfikator sesji, pozostawiając na dysku plik tymczasowy. W moim przypadku żądania następowały na tyle szybko, że serwer otrzymywał żądanie zmiany identyfikatora sesji, usuwał plik tymczasowy, ale nie zdążał na czas z utworzeniem nowego, więc kiedy następowało kolejne wywołanie session_start(), interpreter PHP usiłował wczytać nieistniejący plik, w związku z czym tablica $_SESSION pozostawała pusta. Następnie skrypt, nie widząc w sesji informacji o zalogowanym użytkowniku przekierowywał mnie na stronę błędu braku uprawnień do wykonania akcji. I kółko się zamyka ;]

Linki: [0] http://pl2.php.net/manual/en/function.session-regenerate-id.php - strona manuala języka PHP dotycząca funkcji session_regenerate_id()