Witam, mam taki kontroler i jak widać w metodzie index renderuję widok z formularzem, a w metodzie make waliduję formularz. No i wygląda na to, iż na etapie uruchomienia metody make, tablica POST już nie istnieje. W ogóle nie wiem dlaczego tak się dzieje. Ma ktoś jakiś pomysł ?
Prawdopodobnie bez kodu począwszy od formularza, który generuje POST, przez stronę na której wywoływany jest kontroler, aż do samego kontrolera, który raczyłeś wkleić jako Post Scriptum, trudno będzie coś ustalić, można co najwyżej zgadywać.
Hmm, dziwna sytuacja, ponieważ jak się okazało nie działa sprawdzanie token’a, które wcześniej działało poprawnie.
To klasa Token:
<?php
class Token {
static function create($tokenName = 'token') {
return Session::set($tokenName, md5(uniqid()));
}
static function check($token, $tokenName = 'token') {
// Czy dany token istnieje w sesji && czy istnieje token && czy token z sesji równa się token-owi z formularza
if(Session::has($tokenName) && isset($token) && Session::get($tokenName) === $token) {
Session::delete($tokenName);
return true;
}
return false;
}
}
No a metody check używam przy walidacji. Walidacja znajduje się w metodzie make kontrolera rejestracji, który raczyłem dodać w 1 poście.
Przypomnę, że działało, gdy formularz miałem w tym samym pliku, co formularz. We formularzu mam coś takiego:
Jak usunę sprawdzanie token’a to walidacja formularza działa poprawnie.
#Edit
Na stronie z formularzem wypisałem sobie token’a z sesji, który jest tworzony podczas wywołania metody Token::create(), i te token’y so identyczne, więc ja się poddaję. Wszystko powinno działać…
<?php
class Session {
static function start() {
return session_start();
}
static function get($key) {
return $_SESSION[$key];
}
static function set($key, $value) {
return $_SESSION[$key] = $value;
}
// ta metoda jeszcze nie gotowa
static function flash($key, $value = '') {
if(self::has($key)) {
$session = self::get($key);
self::delete($key);
return $session;
} else {
self::set($key, $value);
}
}
static function has($key) {
if(isset($_SESSION[$key])) {
return true;
}
return false;
}
static function delete($key) {
return session_unset($_SESSION[$key]);
}
}
Ponieważ wcześniej musiałem sprawdzić czy działa mały Query Builder i formularz jak i walidacje, miałem w głównym pliku index. A teraz po rozdzieleniu tych warstw, to nie działa.
Wybacz, ale nie rozdzieliłeś warstw. One nadal są źle zaprogramowane i podlegają tight-coupling. Jedyne co zrobiłeś to wydzieliłeś mocno związaną warstwę do osobnej jednostki kompilacyjnej (bądź w przypadku php interpretacyjnej, jeśli możemy tak powiedzieć). Kod niestety nadal jest mocno związany. Podstawy dependency injection się kłaniają.
Oczywiście, że nie musiałeś. Nie słyszałem o technice tymczasowego zaszywania testów w kodzie produkcyjnym. Zapoznaj się z terminem testy jednostkowe.
Poza tym nadal nie rozumiem. Napisałeś w skrócie: Miałem formularz w tym samym pliku co formularz. Dla mnie to masło maślane, bez sensu. Ale jak chcesz może to jakiś głębszy filozoficzny sens…
Co do samego problemu:
Generalnie masz trochę małe pojęcia o tym co się dzieje w tzw. under the hood podczas tworzenia sesji. Sam fakt, że w kodzie zadeklarujesz sesje nie oznacza, że przeglądarka o niej wie. Wie o niej serwer (stąd na lokalnej stronie wiadomo, że ona istnieje), a do czasu przeładowania strony (a dokładniej otrzymania nagłówków), nie będzie o niej wiedziała przeglądarka. Dzieje się tak dlatego, że sesja jest finalnie i tak implementowana przy pomocy ciastka (dane są przechowywane po stronie serwera, ale musi istnieć identyfikator, który pozwoli nam powiązać sesję z użytkownikiem), które trzeba jakoś przesłać. Nie wiem co chcesz osiągnąć swoim spaghetti, więc proponuje generyczne rozwiązanie, które nie jest najlepsze, ale powinno działać w większości przypadków.
jesli (w tablicy $_SESSION nie istnieje klucz "s") { // to nie wykona się drugi raz, bo zmienną ustawiliśmy w ciele if-a + poinformowaliśmy przeglądarkę z użyciem przekierowania
ustaw obiekt pod kluczem "s" w tablicy $_SESSION
wykonaj przekierowanie, z użyciem GET na stronę na której jesteś //zwrotne przekierowanie, wymagane, aby przesłać nagłówki do przeglądarki (w tym ciastko), dopiero wtedy przeglądarka jest świadoma otrzymania sesji
zapewnij ze dalsza część skryptu się nie wykona // just-in-case, aby nie polegać na "racing condition"
}
// reszta kodu, zależna od sesji
Jeśli mimo wszystko opornie idzie ci zrozumieć co napisałem: Google -> php session need refresh
Jednak u mnie nie zachodzi to co Pan mi wytłumaczył, ponieważ w widoku(tym z formularzem) mam ifa, który sprawdza czy sesja z tokenem istnieje, i to działa. Tzn. po sprawdzeniu czy dana sesja istnieje, wypisuje sobie i to działa, lecz gdy wyślę formularz, ta sesja już nie istnieje.
Zauważyłem jednak coś dziwnego, gdy przechodzę na następną stronę(metodę), to wszystkie zmienne w sesji się kasują. Np. w tym kontrolerze rejestracji tworzę sobie metodę test , w której mam to:
public function test() {
Session::set('test', 'lolololo');
echo "<pre>" , print_r($_SESSION) , "</pre>";
}
a w test2
public function test2() {
echo "<pre>" , print_r($_SESSION) , "</pre>";
}
to mi php wypisuje, że zmienna “_SESSION” jest nieznana ;/ Jak to jest możliwe, że po wywołaniu innej metody, zmienna sesja jest czyszczona ?
Możesz pokazać, jak wyglądają pliki (pełna zawartość pliku, to ważne nie pomijaj niczego z tego pliku), w którym wołasz powyższe metody?
PS Możesz nawet wkleić cały projekt (wszystkie pliki) gdzieś, np. na github. Bo niestety bez podglądu całości projektu, trudno coś powiedzieć, można zgadywać:
Jednak nie robisz przekierowania, tylko tobie się tak wydaje i zmienna z sesja ci się nie wysyła do przeglądarki.
W zasadzie w całości wklejonego kodu nie widziałem wywołania metody session_start() (wołasz ją w ogóle?) bez tego sesja się nie rozpocznie i serializowane dane nie zostaną deserializowane i wepchnięte do tablicy SESSION. Przez to $_SESSION zachowuje się jak zmienna lokalna.
Może to coś konfiguracyjnego, w serwerze, albo w przeglądarce
Tylko tak jak mówię to zgadywanie, bo:
Możesz robić przekierowanie, tylko nie pokazujesz mi tego fragmentu
Możesz wołać session start, tylko nie pokazujesz jakiegoś include’a
Można to wykluczyć, dopiero jak zrobię całościowy code review.
Cóż bywa. Z kodu, który podałeś, nie wynika, że w ogóle było takie wywołanie. Połowicznie zgadłem.
Rada na przyszłość, wrzuć sobie kod na jakiś serwis hostujący system kontroli wersji, który można przeglądać z zewnątrz. Następnym razem poza podaniem klasy, gdzie lokalizujesz efekt końcowy błędu warto też dołączyć całość. Błąd koniec, końców nie musi być tam, gdzie występuje efekt, ale wynikać z jakiś zależności.