Aplikacje internetowe

Bełdziowe spojrzenie na aplikacje internetowe

Hello user

Krótko słowem wstępu.

  • będziemy korzystać z Kohany w wersji 2.2
  • W dzisiejszej notce zajmiemy się rejestracją oraz logowaniem użytkowników w oparciu o moduł Auth

Pierwsza rzeczą jaka musimy się zająć po ściągnięciu i wstępnej konfiguracji Kohany to stworzenie bazy danych oraz tabel wymaganych do działania modułu Auth. Zapytania tworzące tabele dostępne są w pliku modules/auth/views/auth/install.php. Po ich wykonaniu w bazie pojawią się 4 tabele:

  • users – zawierają dane użytkowników
  • roles – zawiera informacje o uprawnieniach użytkowników
  • roles_users – powiązanie użytkowników z uprawnieniami
  • user_tokens – wpisy dotyczące autologowania

Czas na trochę kodu PHP ;-)

Kontroler bazowy

Na początku utworzymy nowy bazowy kontroler dla naszej aplikacji, po którym będą dziedziczyły pozostałe kontrolery. Dzięki niemu uzyskamy obsługę szablonów oraz profilera.

<?php
   class Home_Controller extends Template_Controller 
   {
      // nazwa pliku będącego szablonem 
      public $template = 'lay/main';

      public function __construct( )
      {
         parent :: __construct( );

         // tworzymy obiekt sesji
         new Session;
			
         // tworzymy obiekt profilera
         new Profiler;
      }
   }

?>

Konfiguracja

W pliku config.php należy odkomentować moduł Auth w sekcji modules.

Rejestracja

Proces rejestracji możemy podzielić na dwie części: walidacja danych przesłanych przez użytkownika oraz zapisanie ich w bazie. W celu wykonania pierwszej operacji skorzystamy z klasy Validation.

$post = new Validation( $_POST );
$post -> pre_filter( 'trim' )
      -> pre_filter( 'htmlspecialchars' )
      -> add_rules( 'username', 'required', 'length[3, 32]' )
      -> add_callbacks( 'username', array( $this, '_unique_username' ) )
      -> add_rules( 'password', 'required', 'length[6, 999999]' )
      -> add_rules( 'password2', 'matches[password]' )
      -> add_rules( 'email', 'required', 'valid::email' );

Parametr przekazany podczas tworzenia obiektu określa tablicę, na której będziemy operować. Po stworzeniu obiektu usuwamy skrajne spacje oraz konwertujemy znaki specjalne na encje, a następnie określamy reguły walidacji – pierwszy parametr metody to nazwa pola formularza, pozostałe to reguły walidacji. Dodatkowo korzystając z funkcji zwrotnej sprawdzamy czy podany login jest wolny.

// rozpoczęcie nazwy metody od znaku podkreślenia 
// zablokuje użytkownikom dostęp do niej.
public function _unique_username( $validator, $field )
{
   $login = $validator -> $field;
   if( ORM :: factory( 'user' ) -> username_exists( $login ) )
      $validator -> add_error( $field, 'user_exists' );
}

Po wyciągnięciu wartości pola login tworzymy model reprezentujący tabele users. W kwestii wyjaśnienia

ORM :: factory( 'user' )

jest równoznaczne z:

new User_Model;

Podczas pracy z bazą danych należy pamiętać o konwencji nazywania tabeli i modelów. Nazwy tabel muszą być (jeśli chcemy korzystać z dobrodziejstw ORM / Active Record) w liczbie mnogiej, nazwy modeli zaś w liczbie pojedynczej.

Wracając do powyższej funkcji, sprawdza ona czy w bazie mamy użytkownika o podanym loginie jeśli tak dodajemy błąd do walidatora.

Teraz musimy uruchomić walidator, sprawdzić czy dane pasują do naszych reguł oraz zapisać dane.

if( $post -> validate( ) )
{
   $user = new User_Model;
   $user -> load_data( $post -> as_array( ) );

   if( $user -> save( ) && $user -> add( ORM :: factory( 'role', 'login' ) ) )
      $msg = Kohana :: lang( 'register.successful' );
   else
      $msg = Kohana :: lang( 'register.error' );

   Session :: instance( ) -> set_flash( 'flash', $msg );
   url :: redirect( '/' );
}
else
{
   $this -> template -> content -> post = $post;
   $this -> template -> content -> errors = $post -> errors( );
}

W powyższym kodzie użyliśmy metody load_data, która nie jest standardowo dostępna. Aby móc cieszyć się jej dobrodziejstwem należy w katalogu application/libraries/ utowrzyć plik MY_ORM.php o następującej zawartości:

<?php
   class ORM extends ORM_Core 
   {
      public function load_data( $data )
      {
         foreach ( $data as $field => $value )
         {
            if( !empty( $value ) && array_key_exists( $field, $this -> object ) )
            {
               $this -> $field = $value;
            }
         }
      }
   }
?>

Dzięki temu rozszerzeniu możemy w szybki i prosty sposób wypełnić model danymi.

Wróćmy do kodu dodawania użytkownika. Po wypełnieniu modelu danymi zapisujemy go, a następnie przyznajemy użytkownikowi prawa do logowania. Metoda add dodaje relacje między użytkownikiem (tabela users) i rolami (tabela roles). Na koniec wrzucamy do sesji komunikat z informacją czy rejestracja przebiegła poprawnie.

W przypadku, gdy walidacja zakończy się niepowodzeniem dodajemy do szablonu dwie zmienne – post oraz errors. Pierwsza z nich umożliwi nam dostęp do danych, które podał użytkownik (dzięki czemu będziemy mogli wrzucić je z powrotem do inputów), druga zawiera tablicę z błędami. W tablicy tej role kluczy pełnią nazwy pół formularza, wartości zaś są nazwami reguł, których dane pole nie przeszło. Przykładowo jeśli nie podamy loginu tablica będzie miała następującą postać:

Array
(
    [username] => required
)

Logowanie

Przed przejściem go pisania obsługi logowania delikatnie zmodyfikujemy nasz kontroler bazowy, dodając do jego konstruktora:

$this -> auth = Auth :: instance( );

Dzięki temu uzyskamy łatwiejszy dostęp do modułu Auth w aplikacji.

Tak jak podczas rejestracji tak i podczas logowania cała operacja przebiega w dwóch etapach – walidacja + zapis. Przed sprawdzeniem danych przesłanych od użytkownika możemy sprawdzić czy użytkownik już wcześniej nie został zalogowany, jeśli tak wysyłamy go na stronę główną.

if( $this -> auth -> logged_in( ) )
   url :: redirect( '/' ); 

Jako, że walidacja przebiega w identyczny sposób jak poprzednio pominiemy ją tym razem.

if( $post -> validate( ) )
{
   $user = ORM :: factory( 'user', $post -> login );

   if( !$this -> auth -> login( $user, $post -> password ) )
      Session :: set_flash( 'login_error', Kohana :: lang( 'login.error' ) );
}
else
{
   Session :: set_flash( 'login_error', Kohana :: lang( 'login.error' ) );
}
		
url :: redirect( '/' );

Po sprawdzeniu poprawności danych, pobieramy z bazy dane użytkownika o podanym loginie, a następnie wykonujemy proces właściwego logowania. Jeśli logowanie przebiegnie poprawnie do sesji zostanie obiekt z danymi użytkownika, w przeciwnym wypadku do sesji dodajemy komunikat błędu i wysyłamy użytkownika na stronę główną.

Jeśli teraz chcemy odwołać się do danych użytkownika musimy odwołać się do sesji i wyciągnąć z niej obiekt z danymi. Przykładowo jeśli chcemy poznać login użytkownika :

Session :: get( 'auth_user' ) -> username;

P.S.

W całej notce nie wspomniałem nic o tworzeniu modelu dla stworzonych tabeli, powodem tego jest to, że ów modele już istnieją – są dołączone do modułu Auth.

Cały kod można pobrać stąd.


Tagi: , ,
Kategoria: Kohana, Tutorial


59 komentarzy

  1. ok, głupi byłem, ściągnąłem kohane wraz z modułem, nie było tam jednak wszystkich plików, teraz już działa rejestracja, jednak nie mogę się jeszcze zalogować, kod mam identyczny z Twoim, mimo poprawnej rejestracji wynikiem if(!$this->auth->login($user, $post->password)) jest zawsze false. :(

  2. dodałeś użytkownikowi rolę „login”?

  3. a jak dodać tą rolę??

  4. Jeśli dodajesz usera z poziomu bazy danych to w tabelce roles_users musisz dodać nowy rekord z id roli „login” oraz id użytkownika.

    Jeśli z poziomu kodu, to w notce masz wsio :

    $user -> add( ORM :: factory( 'role', 'login' ) )
    
  5. Szymek W. napisał(a):

    Dzieki za pierwszy dzialajacy example auth’a. Niby wszystko dziala ale tak jak jeden kolega juz wyzej napisal przy rejestracji pole na nickname mam disabled przez co nie moge sie zarejestrowac. Cos pominalem?

  6. Szymek W. napisał(a):

    Sprawdzilem pliki, i znalazlem ze w Register_form.php (libraries) jest:

    protected $disabled = array( ‚username’ );

    zakomentowalem sobie i wszystko dziala ale chcialbym wiedziec czemu milo to sluzyc ;)

  7. Zamysł był tak, że ten sam formularz wykorzystywany jest do rejestracji i edycji danych użytkownika. Właściwość disabled miała być tylko dodawana podczas edycji danych, tak aby użytkownik widział swój login, ale nie mógł go zmienić. Z tego co piszesz ktoś ukradł warunek sprawdzający czy forma jest wykorzystywana do rejestracji czy edycji danych. :)

  8. Szymek W. napisał(a):

    Rozumiem juz.
    Czy zatem nie wystarczy przesniesc wyzej wymieniona linie kodu z klasy Register_Form_Core do User_Form_Core? Generalnie uzyskalem efekt o ktory chodzilo :) Odblokowane w rejestracji i zablokowane w edycji usera.

  9. si, to powinno rozwiązać problem :)

Dodaj komentarz