Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [Symfony]Aktualnie zalogowani użytkownicy.
Forum PHP.pl > Forum > PHP > Frameworki
Valantir
Witam, chciałbym zrobić moduł, który wyświetli mi listę zalogowanych użytkowników. (coś w stylu jak znajomi na facebooku czy nk). Zapisuję sesje do bazy danych:
Kod
storage:
    class: sfPDOSessionStorageOverride
    param:
      session_name: pracainz
      db_table:     session
      database:     propel
      db_id_col:    session_id
      db_data_col:  session_value
      db_time_col:  session_time


Nadpisałem metodę sessionWrite klasy sfPDOSessionStorage:

Kod
class sfPDOSessionStorageOverride extends sfPDOSessionStorage
{
    public function sessionWrite($id, $data)
    {
        // get table/column
        $db_table = $this->options['db_table'];
        $db_data_col = $this->options['db_data_col'];
        $db_id_col = $this->options['db_id_col'];
        $db_time_col = $this->options['db_time_col'];

        $db_user_id_col = 'user_id';
        $user = sfContext::getInstance()->getUser();
        $user_id = false;
        if ($user->isAuthenticated())
        {
            $user_id = $user->getGuardUser()->getId();
        }

        if ($user_id && ($user_id>0))
        {
            $sql = 'UPDATE '.$db_table.' SET '.$db_user_id_col.'= ?, '.$db_data_col.' = ?, '.$db_time_col.' = '.time().' WHERE '.$db_id_col.'= ?';
            try
            {
                $stmt = $this->db->prepare($sql);
                $stmt->bindParam(1, $user_id, PDO::PARAM_STR);
                $stmt->bindParam(2, $data, PDO::PARAM_STR);
                $stmt->bindParam(3, $id, PDO::PARAM_STR);
                $stmt->execute();
            }
            catch (PDOException $e)
            {
                throw new sfDatabaseException(sprintf('PDOException was thrown when trying to manipulate session data. Message: %s', $e->getMessage()));
            }

        }
        else
        {
            $sql = 'UPDATE '.$db_table.' SET '.$db_data_col.' = ?, '.$db_time_col.' = '.time().' WHERE '.$db_id_col.'= ?';
            try
            {
                $stmt = $this->db->prepare($sql);
                $stmt->bindParam(1, $data, PDO::PARAM_STR);
                $stmt->bindParam(2, $id, PDO::PARAM_STR);
                $stmt->execute();
            }
            catch (PDOException $e)
            {
                throw new sfDatabaseException(sprintf('PDOException was thrown when trying to manipulate session data. Message: %s', $e->getMessage()));
            }

        }

        return true;
    }
}

Dodałem kolumnę, która będzie przy sesji wpisywać id użytkownika, który się zalogował ale jest inny problem...
Otóż przy otwarciu strony z formularzem logowania sfGuardPlugin do bazy dodawany jest rekord. Np taki:
Cytat
8nnope4knm9l56p1brabjvt5c3 symfony/user/sfUser/lastRequest|i:1323421511;symfo... 1323421512 0

Następnie przy faktycznym zalogowaniu użytkownika na stronę tworzony jest kolejny rekord:
Cytat
epervhmgatp2t45rpc383u24j7 symfony/user/sfUser/lastRequest|i:1323421619;symfo... 1323421620 1

No i przy wylogowaniu jeszcze jeden rekord jest wstawiany do bazy:
Cytat
1rq7q4g4vb94doodenr7k45rc4 symfony/user/sfUser/lastRequest|i:1323421654;symfo... 1323421654 0

No i teraz pytanie. Jak zgrać to wszystko aby po wylogowaniu rekord danego użytkownika został skasowany a nie wpisywany nowy?
adbacz
A nie możesz zwiększyć czasu przechowywania sesji? Robią się nowe rekordy w DB bo prawdopodobnie, podczas kolejnego requestu, ostatnia sesja już wygasła i SF odnawia sesję uaktualniając COOKIE gdzie przechowywany jest ID sesji. Możesz na przykład każdemu zalogowanemu userowi przypisać ciastko z jakimś ID generowanym podczas logowania. W bazie dodać nową kolumnę w tabeli użytkowników, i przechowywac tam czas kiedy został user zalogowany, czy został zapamiętany, i jego ID z ciastka. Później podczas sprawdzania ilu jest aktuwnych userów, szukasz tylko takich, którzy mają określone dane w kolumnie.

Powiedzmy, że zapamiętanie sesji to 24 godziny, więc sprawdzasz, który user ma liczbę większą od time() - 24godz. (czas w tabeli zapisywany też funkcją time()), i jesli jest więszky (czyli zalogował się conamniej 24 godziny temu) to znaczy, że nadal jest aktywny.

Dodatkowo, jeśli user się wyloguje przed wygaśnięciem sesji, uaktualniasz jego czas w tabeli na 0.
Valantir
Chodzi o to, że podczas aktywności po zalogowaniu drugi wpis się aktualizuje. Jeżeli chodzi o ciastka, to nie pracowałem z nimi pod symfony... Tzn nie ogarniałem jeszcze tego tematu, a bardzo mi się spieszy, bo to praca inżtongue.gif Próbowałem podczas logowania dodać do tabeli rekord z id użytkownika, a podczas wylogowywania usuwać ten rekord ale nie wiem jak pobrać w metodach signin (na końcu metody, bo nie wiem gdzie dokładnie jest tworzona sesja w tej metodzie) i signout (na początku metody zanim sesja wygaśnie) id zalogowanego użytkownika. Gdybym miał id zalogowanego użytkownika w tych metodach, to wstawiłbym do bazy może jakoś to id i wtedy wyciągał z łatwością. A ten czas w którym miejscu miałbym zwiększyć? Nie ogarniam tego tematu...
adbacz
Praca inżynierska, tak? No to fajnie wink.gif Czas wygaśnięcia sesii przechowywany jest w app/config/config.yml pod nazwą session.lifetime zamiast tego co jest, zwiększ do ilu tam sobie chcesz. Najlepiej do 24 godzin.

Nie ogarniasz tematu z ciastkami? A co to za problem wejść na php.net i przczytać o dwóch funkcjach, jedna tworzy a druga usuwa ciacho?

A tak na marginesie, to masz napisany własny system logowania, używasz systemu Symfony czy może jakiegoś innego?

PS. Gdybyś dobrze pomyślał, to szybciej napisałbyś to co ja naskrobałem w moim pierwszym poście, niż rozmowa tutaj teraz o tym.
Valantir
Wiesz, gdy nie ma się z czymś do czynienia, to zawsze wydaje się to trudne do póki się na to nie spojrzy "spokojnym" okiem:) Używam sfGuardPlugin'u do logowania. Jutro jeszcze pomyślę nad tym wszystkim na spokojnie:)
adbacz
Poszukaj w kodzie, kiedy i w jakim miejscu są odpytywane konkretne metody w tym pluginie. Tak najszybciej dojdziesz do tego, gdzie, kiedy i która metoda co robi. W Twoim przypadku musisz znaleźć metodę, która generuje to zapytanie do bazy i sie pod nią podpiąć jakoś. Możesz też poszukać metody, która jest przez tą wysyłającą dane do bazy, i z niej jakoś wyciągać dane o zalogowanym userze. Z resztą o czymś takim już wspominałeś.

Gdzie chcesz dodać ten rekord użytkownika o którym tutaj mowa, w jakiej tabeli:
Cytat
Próbowałem podczas logowania dodać do tabeli rekord z id użytkownika, a podczas wylogowywania usuwać ten rekord


Wg mnie, nalepszym rozwiązaniem, będą ciastka i dodatkowa kolumna w tabeli użytkowników. W tedy, nie będziesz musiał się bawić w szukanie po kodzie tego pluginu, tylko dopiszesz sobie mała klasę, i podepniesz ją pod logowanie i wylogowywanie. Ale to tylko moje zdanie. Szkoda, że nikt inny się nie wypowiedział na ten temat, może jakiś świeży pomysł by padł...
Valantir
Gdzie chciałem dodać? Nie wiem-stworzyć sobie tabelę Aktywni czy coś w tym stylu... No właśnie dzisiaj będę szukał takiego miejsca w tych metodach. I pokombinuję też chyba z tymi ciastkami:) No szkoda, że nikt inny się nie wypowiada, bo chyba to jest dość powszechny problem...?
adbacz
Nie wiem czy taki powszechny. Ja nigdy się z podobnym tematem na forum tutaj, ani nigdzie indziej nie spotkałem. Aczkolwiek sądzę, że to mało przydatna rzecz, jesli pisze się coś, co nie ma nic związanego ze społecznościówką, że się tak wyrażę. Bo jakoś dziwnie sobie wyobrazić portal społecznościowy, który nie udostepnia takiej opcji, lub forum (jak te PHP). Aczkolwiek, jesli ktoś pisze swój system logowania, to bez problemu, nawet nie zastanawiając się zbytnio, napisze to, o czym mowa w temacie, w mgnieniu oka - nie jest to trudne. Gorzej właśnie, jak trzeba to rozwiązać a ma się do czynienia z czymś skryptem, w tedy bez dokumentacji, albo czytania kodu się nie obejdzie niestety.

Pozdrawiam...

PS. Nie opłaca się tworzyć nowej tabeli. Za duże marnotrastwo.
Valantir
Znalazłem fragment kodu, w którym mogę się podpiąć i wstawić dane do bazy. Wielkie dzięki ogólny zarys jak można rozwiązać ten problem i pomoc bez tekstów typu - "czego ty *** nie rozumiesz w tym problemie?" i odsyłania do 30 linków:)tongue.gif
Pozdrawiam i jeszcze raz dzięki

To znowu ja:D piszę w tym temacie, bo tego dotyczy moje pytanie. Jak pobrać opcję session.lifetime?
adbacz
A sprawdzałeś, czy klasa zarządzająca sesją (PDOSessionStorage lub inna) nie przetrzymuje tego czasem w swojej właściwości jakiejś? A tak na marginesie - po co Ci to wyciągać?
Valantir
Bo zrobiłem to trochę inaczej... W każdym bądź razie potrzebne jest mi to, gdyż czas ten wykorzystuje w jednym fragmencie kodu, a nie chcę mieć wpisanego tego na sztywno.
adbacz
No dobra, to było akurat proste i może troszkę na okrągło, ale masz. SF dysponuje możliwością korzystania z plików YML, a więc musi posiadać parser tych plików. A że plik config.yml jest napisany właśnie w YAML to możemy użyć symfonowych bibliotek. Użycie na pliku config.yml:
  1. namespace Twojprojekt
  2.  
  3. use Symfony\Component\Yaml\Yaml;
  4.  
  5. class Klasa {
  6.  
  7. public function pokazConfigAction() {
  8. $array = Yaml::parse('/path/to/app/config/config.yml');
  9. //Pokaże całą tablicę z zawartością pliku config.yml
  10. var_dump($array);
  11. //Dostęp do lifetime sesji
  12. $sessLifetime = $array['framework']['session']['lifetime'];
  13. }
  14. }


Mam nadzieję, że Ci pomogłem. Niestety, nie znalazłem innego rozwiązania (o którym pisałem wcześniej, o klasie która zarządza sesją) to podałem CI najprostsze, jakie udało mi się wymyślić, znaleźć. Powodzenia...
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.