Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: klasa logowanie - gdzie sprawdzac zmienne sesyjne
Forum PHP.pl > Forum > PHP > Object-oriented programming
become
Witam.

Jako ze zaczalem uczyc sie OOP chcialbym sie dowiedziec, gdzie umiescic sprawdzanie czy user jest zalogowany ?
Chodzi o to, ze chce informacje o tym czy jest zalogowany trzymac w sesji. I teraz jak zorganizowac klase logowanie ?
Chcialbym przy kazdym przeladowaniu strony sprawdzic, czy istnijeje zmienna sesyjna np. 'userlogin' i na podstawie jej wartosci zalogowac go. Czy calosc operacji zrobic w klasie, czy np. gdzies w kodzie najpierw sprawdzic czy zmienna sesyjna istnieje i dopiero pozniej ewentualnie utworzyc klase Logowanie(), czy raczej przy kazdym wywolaniu strony tworzyc klase Logowanie a w środku niej sprawdzac czy user jest zalogowany ?
Cezar708
Lepiej stworzyć klasę User, i w niej trzymać pole $userlogin, które jest oparte o zmienną sesyjną. a w momencie logowania po prostu tę zmienną ustawić. Potem w każdym miejscu kodu, gdzie wejście dozwolone tylko dla zalogowanych należy sprawdzać czy w obiekcie klasy User jest ustawione to pole.

przykład:
  1. <?php
  2. class User{
  3.  
  4. private $userlogin;
  5.  
  6. function __construct(){
  7. if ( isset($_SESSION['userlogin']) && $_SESSION['userlogin'] == 1 ){
  8. $this->userlogin = true;
  9. } else {
  10. $this->userlogin = false;
  11. }
  12. }
  13.  
  14. public function isLogged(){
  15. return $this->userlogin;
  16. }
  17. }
  18.  
  19. // klasę user login najlepiej tworzyć gdzieś we front kontrolerze (albo w pliku, którzy zawsze będzie w pierwszej kolejności odpalany) 
  20. $user = new User();
  21.  
  22. // i potem w każdej odpowiedniej podstronie można go sprawdzać 
  23. if ( !$user->isLogged() ){
  24. die('trza się zalogować');
  25. }
  26. ?>
become
Dzieki za info.

ale tak sobie myslalem. chyba raczej sam proces logowania powinna zrobić inna klasa - prawda ?
obiekt User powinien zostać zwrócony przez np. klasę Logowania(). Mam racje ?
Cysiaczek
Cytat
// i potem w każdej odpowiedniej podstronie można go sprawdzać
if ( !$user->isLogged() ){
die('trza się zalogować');
}


Niekoniecznie, bo skoro tworzysz instancję klasy User we front controllerze, to można tam też uruchomić proces autoryzacji i jej obsługę. Chyba, że Tobie chodzi o warstwę widoku. smile.gif

@beceme - Wszystko zależy od tego, czy User to obiekt pasywny, czy aktywny. Jeśli jest pasywny, to powinien być zarządzany przez inną klasę (np. userManager, Authorization itp. - nazwa nie jest tu tak ważna).
  1. <?php
  2. $auth=new Authorization();
  3. $user=new User($context->username, $context->userpass);
  4. $auth->login($user);
  5. //lub
  6. $auth=new Authorization($context->username, $context->userpass);
  7. $auth->login();
  8. $user=$auth->getUser();
  9. [php]
  10.  
  11. Je&#347;li User jest aktywna, to może zawierać metody autoryzacji.
  12. [php]
  13. $user=new User($context->username, $context->userpass);
  14. $user->login();
  15. ?>


Osobiście skłaniam się ku pierwszemu rozwiązaniu, choć w jakimś małym CMS'ie obsługiwanym przez jedną osobę nie trzeba rozbudowywać autoryzacji, więc drugie rozwiązanie wystarczyłoby w zupełności. Musisz patrzeć na system pod kątem relacji w jakie wchodzą jego obiekty. Np. patrząc logicznie, to klasa User powinna być tylko zestawem danych na temat użytkownika, a więc odzwierciedleniem wiersza z tabeli bazy danych (albo z pliku). Tym samym powinna zawierać metody do operowania tymi danymi, natomiast nie powinna zawierać metod, które wpływają na cały system. Taką metodą jest np. metoda User::login() - użytkownik rejestruje się sam, co jest nielogiczne. Kończąc - masz rację - inna klasa, której celem jest autoryzacja użytkowników jest bardziej zorientowana obiektowo.

Pozdrawiam.
become
przepisuje pewien system i przy okazji chciałbym sie nauczyć programowania obiektowego.
jezeli chodzi o np. Urzytkownika serwisu, to chodzi mi o takiego jak w serwisie wiadomosci24.pl czy interia360.pl lub iThink.pl

Serwis który przepisuje jest bardzo podobny.
Jezeli uzytkownik jest zalogowany to ma dostep do swojego panelu. Moze komentowac i oceniac inne artykuly.
To taka podstawa.

Chce to zrobić tak.

Obiektami bedą (jest ich 11):

1. Uzytkownik (autor).
2. Lista autorow. (bedzie korzystac z obiektu Uzytkownik)
3. Kategoria
4. Lista kategorii (korzysta z obiektu kategoria)
5. Zajawka artykulu (autor, tytul, wstep)
6. Lista zajawek artykulów w danej kategorii. (bedzie korzystac z obiektu 'zajawka artykul')
7. Artykul (bedzie rozszerzal 'zajewke artykulu')
8. Komenatrz
9. Lista komentarzy. (bedzie korzystac z obiektu 'komentarz')
10. Ocena artykulu. (to zrobic jako oosbny obiekt, czy raczej parametr w Artykule ?)
11. Logowanie

Artykul bedzie zawierał w sobie: obiekt Autor, obiekt 'Lista Komentarzy', obiekt 'oceny'
Myslalem tez, zeby obiekt Logowanie zawierał w sobie obiekt 'autor'. Wtedy klasa autor moze byc wykorzystana do stworzenia obiektu autor np. w 'liście autorów' oraz mozna go wstawić do obiektu 'Logowanie' jako informacje o zalogowanym uzytkowniku.

Nie wiem natomiast gdzie umiescic dane statystyczne jak oceny artykulu, ilosc przeczytan artykulu itp.
Czy bezposrednio w artykule, czy tworzyc jakies klasy pod to ?

Mam nadzieje ze ogolnie dobrze to rozplanowalem.

Natomiast w innym wątku ktoś proponował mi rozbicie kazdej klasy na 2 - jedna zawierajaca glowne dane i druga - klasa _model, ktora bedzie zawierac wszystkie metody operujace na danych.
Czyli byłoby klasa autor i klasa autor_model().
Mysle sobie ze klasą modelową można byłoby zrobić klasy operujace na listach (artykulow, autorow) i w niej zaimplementowac metody do pobierania listy autorów, jak i do pobrania 1 autora.

Jak uważacie ?
Cysiaczek
Cytat
Natomiast w innym wątku ktoś proponował mi rozbicie kazdej klasy na 2 - jedna zawierajaca glowne dane i druga - klasa _model, ktora bedzie zawierac wszystkie metody operujace na danych.


To właśnie jest podział na obiekt danych i obiekt manipulujący danymi (z user i authroziation wykazałem to samo). Wydaje mi się, że dobrze myślisz. Osobiście zwykem nazywać tak powiązane klasy wg konwencji.
Klasa
klasaManager

Żeby Ci jeszcze zamieszać, to klasaManager może posiadać jeszcze jeden obiekt - klasaCollection, który przechowuje obiekty klasy Klasa. Myślę, że ta trójka się sprawdza doskonale z niemal każdym rodzajem obiektow - i doskonale spisze się z parami
3. Kategoria
4. Lista kategorii (korzysta z obiektu kategoria)

5. Zajawka artykulu (autor, tytul, wstep)
6. Lista zajawek artykulów w danej kategorii. (bedzie korzystac z obiektu 'zajawka artykul')

Wykorzystaj istniejące rozwiązania, jak chociażby Propel, dzęki któremu pozbędziesz się kłopotu z ciągłym pisaniem kodu pobierającego dane z bazy i przetwarzającego go na obiekty. Propel robie jakieś 70% pracy za Ciebie (oczywiście przy użyciu jakiegoś dobrego frameworka)

Pozdrawiam.
become
Tyle ze dopiero sie ucze OOP, wiec nei wiem czy bede od razu korzystał z Propela albo jakiegos calosciowego frameworka.
Mysle ze pierwsze co, to dobrze zaprojektowac obiekty.
Nawet jezeli zrobie 80% obiektowo i 20% proceduralnie to i tak bedzie to lepiej niz teraz, kiedy obiekty to tylko klasy PEAR:biggrin.gifB i Smarty smile.gif i ewentualnie 1 czy 2 wlasne klasy.
Sedziwoj
@Cysiaczek
Rozbijanie ma sens kiedy jest to potrzebna, bo np. masz zawsze jednego User'a w systemie na raz (taka właściwość skryptów po stronie serwera) więc tworzenie kolekcji jest bezcelowe.
Co do autoryzacji, to jest już coś osobnego, bo przecież same informacje o użytkowniku jak i operacje z nim związane się mogą nie zmienić podczas gdy system autoryzacji tak.
Samo rozbicie na dane - operacje, jest bez sensu jeśli nie masz ku temu powodu. Ja używam obiektów z danymi wtedy, gdy operacje na nich wykonuje parę różnych obiektów. Ale gdy masz użytkownika, to wiadomo że możesz pobrać jego posty, że ta metoda wykorzystuje inny obiekt to już nas nie obchodzi, ale jest związana z użytkownikiem więc nie ma sensu jej nie mieć razem z danymi.
Ja bym jednak był za tym że obiekt użytkownika agreguje obiekt autoryzacji, aby kod był czytelniejszy. Choć to jak zawsze zależy od konkretnej sytuacji.

@become
Propel może z początku wydawać się skomplikowany, ale jak już będziesz umiał nim się posłużyć to będzie przyjemność, do tego pokaże Ci pewne podejście obiektowe co Ci się przyda. Tak samo skorzystanie z dobrego framework, bo będziesz pracować w obiektowym, co pomoże Ci w jaki sposób to robić. Choć na pewno na Twoim miejscu bym użył Propela, a frameworka potem (np. Symfony).
Cysiaczek
@Sedziwoj - jasne - każdy pisze jak mu wygodniej, byle miało to ręce i nogi smile.gif
Z niektórymi rzeczami jednak nie do końca się zgadzam
Cytat
masz zawsze jednego User'a w systemie na raz (taka właściwość skryptów po stronie serwera) więc tworzenie kolekcji jest bezcelowe.


Obiekt User potraktowany jako obiekt danych może zostać wykorzystany w różnych częściach systemu.
1. Sesja użytkownika
2. Zakładanie / modyfikacja danych użytkownika
3. Listowanie danych o wielu użytkownikach (np w panelu admina)

W punkcie #3 kolekcja jest jak najbardziej użyteczna. Jej przydatność widać też tam, gdzie wykonujemy wiele różnych operacji na obiekcie User - obiekt trzeba pozyskać, sprawdzić jego stan, a w razie konieczności zapisać. Jeśli wszystko to będzie agregował obiekt User, to jego funkcjonalność strasznie się rozrośnie i chcąc nie chcąc - stanie się on zarządcą samego siebie uzależnionym od wielu innych obiektów i wyposazonym w wiele okazjonalnych metod np. User::getPosts(). Automatycznie przenośność kodu spada do zera.

Pozdrawiam.
become
czyli jak byscie polecali mi to zrobic ?
NoiseMc
  1. <?php
  2. $auth=new Authorization();
  3. $user=new User($username, $userpass);
  4. $auth->authenticate($user);
  5. ?>


Mi osobiscie tez najbardziej podoba sie takie rozwiazanie, dodatkowo obiekt Authorization moglby uzywac roznych adapterow jak na przyklad DBAuthorizationAdapter lub FileAuthorizationAdapter jezeli chcialbys w przyszlosci zmienic sposob przechowywania danych potrzebnych do autoryzacji.
Korzystajac z Zend Framework mam plugin ktory przed uruchomieniem kazdej akcji sprawdza czy uzytkownik jest zalogowany jezeli nie to go przenosi do strony logowania:

  1. <?php
  2. class AuthenticationPlugin extends Zend_Controller_Plugin_Abstract
  3. {
  4. function preDispatch(Zend_Controller_Request_Abstract $request)
  5. {
  6. $auth = Zend_Auth::getInstance ();
  7.  
  8. if (! $auth->hasIdentity ())
  9. {
  10. // Przekieruj do strony logowania
  11. }
  12. }
  13. }
  14. ?>


A sam proces logowania:

  1. <?php
  2. $user = new Users_User ($userName, $password);
  3. $authAdapter = new Noise_Auth_Adapter_UserNamePassword ($user);
  4. $result = $this->auth->authenticate ($authAdapter);
  5.  
  6. switch ($result->getCode ())
  7. {  
  8. case Zend_Auth_Result::SUCCESS:
  9. // Pokaz strone
  10. break;
  11.  
  12. case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
  13. $errorMessage = 'Inactive User';
  14. break;
  15.  
  16. default:
  17. $errorMessage = 'Invalid UserName or Password';
  18. break;
  19. }
  20. ?>


Natomiast sam adapter:

  1. <?php
  2. class Noise_Auth_Adapter_UserNamePassword implements Zend_Auth_Adapter_Interface
  3. {
  4. private $user;
  5.  
  6. public function __construct ($user)
  7. {
  8. $this->user = $user;
  9. }
  10.  
  11. public function authenticate ()
  12. {
  13. $usersModel = new Users_Model ();
  14.  
  15. $user = $usersModel->getUserByUserNameAndPassword ($this->user->userName, $this->user->password);
  16.  
  17. if (empty ($user))
  18. {
  19. return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND, null);
  20. }
  21. else 
  22. {
  23. if ($user->isActive)
  24. {
  25. return new Zend_Auth_Result (Zend_Auth_Result::SUCCESS, $user->userID);
  26. }
  27. else 
  28. {
  29. return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID, null);
  30. }
  31. }
  32. }
  33. }
  34. ?>


Co do przechowywania zmiennych sesyjnych to ... jak widac w pluginie ( $auth->hasIdentity (); ) zajmuje sie tym objekt Auth i to tam zapisywane i odczytywane sa dane z sesji.
Sedziwoj
Cytat(Cysiaczek @ 29.11.2007, 13:17:39 ) *
@Sedziwoj - jasne - każdy pisze jak mu wygodniej, byle miało to ręce i nogi smile.gif
Z niektórymi rzeczami jednak nie do końca się zgadzam
Obiekt User potraktowany jako obiekt danych może zostać wykorzystany w różnych częściach systemu.
1. Sesja użytkownika
2. Zakładanie / modyfikacja danych użytkownika
3. Listowanie danych o wielu użytkownikach (np w panelu admina)
W punkcie #3 kolekcja jest jak najbardziej użyteczna. Jej przydatność widać też tam, gdzie wykonujemy wiele różnych operacji na obiekcie User - obiekt trzeba pozyskać, sprawdzić jego stan, a w razie konieczności zapisać. Jeśli wszystko to będzie agregował obiekt User, to jego funkcjonalność strasznie się rozrośnie i chcąc nie chcąc - stanie się on zarządcą samego siebie uzależnionym od wielu innych obiektów i wyposazonym w wiele okazjonalnych metod np. User::getPosts(). Automatycznie przenośność kodu spada do zera.
Pozdrawiam.


A co to ma wspólnego z przechowywaniem kolekcji obiektów User w obiekcie do autoryzacji?

@NoiseMc
Opracowałem coś w sumie podobnego, tylko że sposób autoryzacji jest ustawiany w configu (z prostego powodu, w zależności od tego czy to jest developerska czy nie inaczej jest sprawdzana...) do tego nie ma u mnie takiego czegoś jak użytkownik, jest login i hasło, więc nie utworzyłem tego obiektu, zbędny jest (przerost formy nad treścią by był). No i jest o wiele bardziej rozbudowane sprawdzanie dostępu... ale to już nie ten temat ;]
Cysiaczek
Cytat
A co to ma wspólnego z przechowywaniem kolekcji obiektów User w obiekcie do autoryzacji?


Trochę się zgubiłem - nigdzie nikt nie pisał, żeby przechowywać kolekcję obiektów w obiekcie autoryzacji.
Sedziwoj
Cytat(Cysiaczek @ 30.11.2007, 10:53:32 ) *
Trochę się zgubiłem - nigdzie nikt nie pisał, żeby przechowywać kolekcję obiektów w obiekcie autoryzacji.


Może to ja źle zrozumiałem...
Jedno jest pewne ORM daje pewną już strukturę obiektów, w Propelu mamy klasę pustą dziedziczącą po Base, w niej powinniśmy pisać metody związane z tymi danymi.

Tak mnie zastanawia jakie jest lepsze rozwiązanie przypisania konkretnego sposobu autoryzacji, czy jak tu było podane czyli przez przekazanie obiektu, czy jak ja mam przez konfigurację. W sumie to też zależy... ale raczej jest jednak autoryzacja dla jednego systemu. A w moim rozwiązaniu wystarczy zmienić jeden wpis w configu i wszędzie jest zmieniona autoryzacja. Po prostu pytanie w jaki sposób obiekt autoryzacji ma agregować konkretyzację logowania...
Cysiaczek
Ja wydzieliłem osobny moduł autoryzacji, który jest napisany zgodnie z naturą mojego frameworka, czyli jako zwykły moduł aplikakcji.
Ma on jednak ściśle zdefiniowany interfejs i zwraca dane w formacie czytelnym dla frameworka.
Sam framework posiada w konfiguracji możliwość zdefiniowania, jaki moduł i jaka akcja odpowiadają za autoryzację. Po rozwiązaniu żądania, na szczycie stosu zadań do wykonania jest umieszczana ta akcja i framework jak gdyby nigdy nic, zaczyna wykonywać stos akcji (wg FIFO).
Pierwsze wykona się sprawdzenie uprawnień. Potem to już tylko wyobraźnia ogranicza działania. Można przekierować do innej akcji, 404, wyświetlić exception etc. Można też wykonać akcję zawartą w specjalnej sekcji o nazwie <onDeny>, która definiuje dla konketnego modułu lub jeszcze dokładniej - dla każdej akcji zachowanie przy stwierdzonym braku dostępu.
Dlaczego tak to opisuję? Bo jeśli umieścimy autoryzację w kontrolerze strony, to kaplica - zostaje nam albo header(), albo ręczna obsługa z if else w kodzie, co mi się osobiście wydaje programistycznym średniowieczem.

@sedziwoj - moim zdaniem tylko konfiguracja wchodzi w grę

Pozdrawiam,
Sedziwoj
@Cysiaczek

Pomijasz jeden przypadek, kiedy to dane czy dana osoba ma dostęp do danej treści czy nie możesz ustalić dopiero w konkretnej akcji kiedy masz już te dane, wcześniej nie można bo ich po prostu nie masz.
Np. masz dostęp do artykułów z grupy 9, do innych nie masz. Wszyscy mają dostęp do tych z 1... Więc nie możesz przed rozpoczęciem wykonywania akcji stwierdzić czy ma dostęp, czy tez nie ma. Do tego jak nie ma dostępu wcale nie musi być kierowany na ogólną stronę logowania, tylko np. masz tytuł a pod spodem zamiast treści formularz logowania.
Cysiaczek
To prawda, tylko chyba na poziomie FW nie da się rozwiązać tego problemu bez powiązania go z konkretną treścią. Sama techniczna możliwość dodania formularza logowania jest, bo po prostu taki formularz jest generowany automatycznie, lub jest pobierany jako partial.
Chętnie się dowiem, jak zrobiłeś to u siebie smile.gif

Pozdrawiam.
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.