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.


59 odpowiedzi do “Hello user”

  1. Mam kohane 2.3 i w tej wersji nie ma katalogu view w folderze auth. Skąd mam wziąć zrzuty tych tabel?

  2. Witam,
    Mam wielką prośbę. Chciałem zainstalować ten przykład z galeria.rar ale niestety nie działa i nie wiem gdzie robię coś nie tak. Konfiguracja: Apache 1.3.37, PHP 5.2.2, Kohana 2.3.1. Kohanę zainstalowałem i sprawdziłem – działa. Na to nałożyłem całą zawartość galeria.rar. Zmieniłem config.php (sitedomain na /app/) i database.php na swoją bazę i dodałem .htaccess jak w kohanaphp.com. W bazie zainicjowane tabele zgodnie z opisem. I to wszystko. /app/examples działa bez problemu.
    Ale /app/ wywala się w dziwny sposób. Mam błąd Use of undefined constant User_Mode, co jest przecież bardzo dziwne bo „Use of undefined constant” to podstawa autoloadowania klas. Nie mam pojęcia co z tym dalej zrobić. Kilka razy próbowałem od zera całej instalacji. W sumie kilka godzin zmarnowane. Bardzo byłbym wdzięczny za jakąś wskazówkę.
    Poniżej kopia tego co wychodzi na ekranie.

    Błąd wykonania
    Wystąpił błąd który uniemożliwił załadowanie strony. Jeśli problem się utrzymuje prosimy skontaktować się z administratorem strony.

    C:/Program Files/Apache Group/Apache/htdocs/app/modules/formation/libraries/Model_Formation.php [28]:

    Use of undefined constant User_Model – assumed 'User_Model’

    Zrzut stosu (Stack Trace)
    application\libraries\Login_Form.php [9]:
    Model_Formation_Core->__construct( )
    application\controllers\home.php [22]:
    Login_Form_Core->__construct( )
    Home_Controller->__construct( )
    system\core\Kohana.php [235]:
    ReflectionClass->newInstance( )
    Kohana::instance( )
    system\core\Event.php [209]:
    call_user_func( Array
    (
    [0] => Kohana
    [1] => instance
    )
    )
    system\core\Bootstrap.php [55]:
    Event::run( system.execute )index.php [106]:
    require( system\core\Bootstrap.php )

  3. config.php jest z wypakowany z archiwum. Zmieniłem tylko (sitedomain na /app/) i jest tam aktywny Auth i formation. Oba moduły też są wrzucone z archiwum.

  4. Zaciągnąłem jeszcze raz z kohany instalkę czystą bez modułów. Nałożyłem na to galeria.rar. Baza jest dobrze skonifigurowana bo napisałem kontroler czytający przez Database i on działa.
    A /app/index.php się wywala zawsze. Może prześlę (jeśli można) na priva spakowany folder?
    Jestem załamany myślałem, że coś będę mógł w kohanie napisać a tu takie problemy na początek.

  5. wystarczyło dać index.php :
    error_reporting(E_ALL & ~E_STRICT & ~E_NOTICE);
    ^^^^^^^^^^^^^^^^
    Ten błąd jest z grupy E_NOTICE ;). A błąd musi być bo bez tego nie byłoby autoloadu klas.

    Nie wiem, czy to znawcy poprawiają zaraz po instalacji kohany?

  6. Witam. Mam problem z pozyzszym przykladem.
    Mianowicie, nie mogę się zalogować. Cala rejestracja przebiega poprawnie. Niestety przy logowaniu cały czas ma problem ze podaje złe hasło….
    w konfigu nic nie zmieniane. w bazie hasła 50 znaków.
    Z góry dzięki za pomoc

  7. hmm ciezko powiedziec nie majac dostepu do Twojego kodu, spr czy w tabelce „roles_users” masz powiazanego usera z rola „login”

  8. Tabele są w porządku, wszystko wypełnione jak należy.

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

    if ( ! $user->loaded){
    $post->add_error(’username’, 'not_found’);
    }elseif ($this->auth->login($user, $post->password)) {
    url::redirect($this->session->get_once(’referrer’));
    }else{
    $post->add_error(’password’, 'incorrect_password’);
    }
    wszystko wskazuje na to ze w tym miejscu: $this->auth->login($user, $post->password) hasło jednak się nie zgadza, jednak wpisuje takie jak przy rejestracji. czy to moze byc problem hashowania hasla?

  9. A ja mam takie pytanie…

    Załóżmy że cały serwis www składa się z kilka serwisów. Każdy serwis ma swój własny identyfikator np. website_id. Jak teraz zrobić żeby użytkownicy z poszczególnych serwisów byli niezależni?

    Tzn. mam np. w bazie w każdej tabeli kolumnę website_id.
    Jak teraz zrobić żeby przy logowaniu, rejestracji, przyznawaniu praw dodatkowo był sprawdzany warunek website_id=’jakas_liczba’ ?????

  10. ciężko doradzić coś konkretnego nie mając wglądu w kod, aczkolwiek jeśli pole `website_id` masz w każdej tabelce to zapewne najprościej będzie rozszerzyć klase ORM tak aby w chwili wykonania metody get wykonany był kod w stylu
    $this -> db -> where( 'website_id', $zmienna_z_id_serwisu )

  11. Poprzedni komentarz można uznać za niepotrzebny.

    Mam teraz taki problem.
    W bazie danych dodałem usera o id 1 i loginie Heniek w tabeli roles_users dałem mu id roli 2

    Przy logowaniu pojawia się w sesji taki błąd:
    _kf_flash_ : Array
    (
    [login_error] => old
    )
    Oczywiście logowanie stworzone na podstawie artykułu (wręcz skopiowane)
    Sprawdzam też czy jest zalogowany za pomocą if($this -> auth -> logged_in( ))
    Niestety wynik jest FALSE

  12. Czy muszę gdzieś potwierdzać rejestrację? Ja jej nie wykonałem tylko przez phpmyadmin dodałem usera, więc może coś z tym jest źle

  13. Błędu jako takiego to nie zwraca, ale system nie wykrywa zalogowania i Profiler pokazuje coś takiego:
    _kf_flash_

    Array
    (
    [login_error] => old
    )

  14. a czy samego użytkownika też dodałeś przez phpMyAdmina? bo jeśli tak to tu jest problem, Auth do hasła dodaje także sól mającą utrudnić jego złamania; tak więc jeśli po prostu dodałeś usera przez phpMyAdmina hasło nie zawiera soli i przez to nie możesz się zalogować

  15. Już sobie zrobiłem rejestrację.
    Teraz mam taki problem przy logowaniu. Gdy podaje login, który mam w bazie to żaden błąd się nie pojawia. Zaś gdy podaje taki, którego nie ma wówczas pojawia się takie coś:

    Wystąpił błąd który uniemożliwił załadowanie strony. Jeśli problem się utrzymuje prosimy skontaktować się z administratorem strony.

    C:/Program Files/Apache Group/Apache2/htdocs/Heniek_CMS/modules/auth/libraries/Auth.php [227]:

    Uninitialized string offset: 1

  16. Czy mógłbyś mi podpowiedzieć co powinienem poprawić żeby włączyć zapamiętanie logowania?

  17. w pliku auth_user.php w okolicach lini 65 masz coś takeigo:

    if ($this->loaded AND Auth::instance()->login($this, $array['password']))
    

    trzeba to zamienić na:

    if ($this->loaded AND Auth::instance()->login($this, $array['password'], (bool)$array[ 'remember' ] ))
    

    gdzie remember to nazwa checkboxa „Zapamiętaj mnie” :)

  18. Tutek fajny, ale mam pytanie, w jaki sposób sprawdzić czy email także jest unikatowy ?

  19. jeszcze tak patrzę to przykładowe pliki są właściwie w ogóle inne, trudno jest się połapać, patrząc na to co jest napisane w tutku a potem na przykładowe pliki…

  20. przykładowo przy opcji szukania we wszystkich plikach, nie mogłem znaleźć np. ’-> pre_filter( 'trim’ )’ i innych rzeczy z rejestracji

  21. a to dlatego, że w 2giej części tutka jest opis modułu do obsługi formularzy, który przejmuje część pracy, która została opisana w tej notce :) a dołączone źródła są „najnowsza wersja”

  22. i to może być problem :P
    Ogólnie tutorial nie opisuje nazw plików oraz dokładnie gdzie je wrzucać, jakieś podstawowe doświadczenie z MVC i frameworkami mam, ale Kohana to nowość i lekko mówiąc wszystko mi się miesza :D

  23. A ja mam takie pytanie małe, gdyż u mnie występuj błąd. To znaczy nie błąd, lecz dość duży problem. Na stronie rejestracji pole jest wyłączone. Czy można je w jakikolwiek sposób uaktywnić?

  24. czegoś nie rozumiem, bo piszesz , że modele już istnieją, czyli masz na myśli np. username_exists() ? jeśli tak to mi nie widzi tej funkcji

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Wymagane pola są oznaczone *