Blog (3)
Komentarze (179)
Recenzje (0)
@knykuCakePHP w praktyce. Logowanie z funkcją 'zapamiętaj mnie na...'

CakePHP w praktyce. Logowanie z funkcją 'zapamiętaj mnie na...'

22.05.2013 20:05, aktualizacja: 22.05.2013 20:32

Jako, że jest to mój pierwszy post - przedstawię się. Kamil Falgowski, lat 22, pracuję w agencji reklamowej we Wrocławiu jako człowiek od PHP.

Niestety w pracy nie jest mi dane korzystać z różnych dobrodziejstw oddanych zupełnie za darmo dla ludu przez zespoły programistów pracujących nad aplikacjami przez wiele lat. Jednak w swoich projektach nikt mi tego nie zabrania. I tu właśnie pojawia się tytułowe CakePHP.

Jest wiele innych framework'ów PHP, podobno lepszych, wygodniejszych i tak dalej, i tak dalej... Ale po co? CakePHP - podręcznikowe podejście do MVC, wygoda, jasne konwencje nazewnictwa. Czego chcieć więcej? No może jeszcze tego, że jak wpiszę coś w google to znajdę dziesiątki stron i forów na dane zagadnienie. Tak, to jest dostajemy w zestawie.

No to zaczynamy. Co będzie nam potrzebne?

  • Apache - osobiście polecam xampp
  • Najnowsze wydanie CakePHP do ściągnięcia tutaj
  • Środowisko pracy, polecam Sublime Text 2
  • Chwilka wolnego czasu i trochę chęci.

Nie będę się tutaj rozpisywał nad założeniami modelu MVC, tylko w skrócie: model, view controller. Model - część aplikacji odpowiadająca całej logice, np połączenia z bazą danych, View - widok, czyli wszystko to co chcemy aby widział przeglądający, Controller - swoisty klej, który ma za zadanie połączenie modelu z widokiem.

Konfiguracja CakePHP

Po skopiowaniu plików ściągniętych ze strony framework'a i wpisaniu w pasek adresu

localhost/nazwafolderuzcakephp
pojawi się powitalna strona, gdzie będą wypunktowane wszystkie sprawy którymi należy się zająć przed przystąpieniem do pracy.

Najważniejsza się konfiguracja bazy danych. Zrobimy to edytując plik

/app/Config/database.php
Powinien mieć on mniej więcej taką strukturę:

<?php
class DATABASE_CONFIG {

	public $default = array(
		'datasource' => 'Database/Mysql',
		'persistent' => false,
		'host' => 'przykladowy.host',
		'login' => 'login',
		'password' => 'haslo',
		'database' => 'nazwabazy',
		'prefix' => '',
		'encoding' => 'utf8',
	);
}

Table w bazie danych

Będziemy potrzebować tylko jednej tabeli w bazie danych. Mianowicie

users
I tutaj mamy pierwszą styczność z konwencjami nazewnictwa w CakePHP. Jeśli kontroler ma się nazywać Users, tabela w bazie danych powinna się nazywać tak samo, oczywiście nie musi, lecz zaoszczędzi nam to pisania zbędnych w tym momencie linii kodu. Natomiast model w tym wypadku musi nazywać się User, czyli liczba pojedyncza. Tyle na razie o konwencjach.

Niech tabela ma następujący układ:


CREATE TABLE IF NOT EXISTS `users` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL,
  `name` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL,
  `last_login` datetime NOT NULL,
  `created` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=latin2;

AppController

AppController jest to kontroler główny, czyli taki, po którym dziedziczyć będą wszystkie tworzone przez nas kontrolery. Znajduje się w 

/app/Controller/AppController.php
Tutaj musimy dodać komponent wbudowany w CakePHP, czyli AuthComponent oraz CookieComponent. Tak więc, uczyńmy to:


class AppController extends Controller {

	public $components = array(
        'Cookie',
		'Auth' 
	);
...

Tym sposobem, AuthComponent będzie ładowany w każdym miejscu naszej aplikacji, na czym nam zależy, bo nie chcemy przecież, aby ktoś mógł wejść tam gdzie nie może.

W AppController musimy jeszcze zadbać o to jak ma się zachowywać ten komponent. Posłuży nam do tego metoda

beforeFilter()
wykonująca się zawsze przed wykonaniem jakichkolwiek innych czynności.


class AppController extends Controller {
...
public function beforeFilter() {
       $this->Auth->deny(); // z góry blokujemy dostęp do każdej strony
       if (!$this->Auth->loggedIn() && $this->Cookie->read('remember_me_cookie')) { //sprawdzamy czy  użytkownik nie jest już zalogowany oraz czy istnieje ciasteczko pozwalające na zalogowanie się
		$cookie = $this->Cookie->read('remember_me_cookie');
		$user = $this->User->find('first', array( // sprawdzamy czy w bazie istnieje użytkownik o loginie i haśle pozostawionym w ciasteczku
			'conditions' => array(
				'User.username' => $cookie['username'],
				'User.password' => $cookie['password']
			)
		));

		if ($user && !$this->Auth->login($user['User'])) { // jeśli te dane są nieprawidłowe przekierowanie na formularz logowania
			$this->redirect(array('controller' => 'users', 'action' => 'login'));
			}
		}
		$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login'); // tutaj definiujemy akcje logowania
		$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login'); // akcja wylogowania
		$this->Auth->loginRedirect = array('controller' => 'index', 'action' => 'index'); // akcja wykonywana po poprawnym zalogowaniu się
}

Tym sposobem obsługujemy cały proces logowania się

Model

Przyszedł czas na stworzenie modelu modułu do zarządzania użytkownikami. Tworzymy plik

/app/Model/User.php
Tutaj przyszedł czas na zadbanie o poprawną walidacje wpisywanych danych przez użytkowników.


class User extends AppModel {

	public $validate = array(
		'username' => array(
			'rule1' => array(
				'required' => true, 
				'rule' => 'notEmpty',
				'message' => 'To pole jest wymagane'
				),
		'password' => array(
			'required' => true, 
			'rule' => 'notEmpty',
			'message' => 'To pole jest wymagane'
			),
		);

Tym sposobem pola username oraz password będą wymagane podczas logowania.

Kontroler

Przyszedł czas na zaprogramowanie akcji które mają się wydarzyć podczas logowania. Stworzymy metody login, logout potrzebne do obsługi tych czynności.


class UsersController extends AppController {
...
public function login() {
	if ($this->Auth->loggedIn()) { // sprawdzamy czy już zalogowany a jeśli tak przekierowanie na stronę główną
		$this->redirect(array('controller' => 'index', 'action' => 'index'));
	}
	if ($this->request->is('post')) { // kontrolujemy czy zapytanie zostało wysłane metodą 'post'
		if ($this->Auth->login()) { // logujemy się
			if ($this->request->data['User']['remember_me'] == 1) { // jeśli w formularzu zaznaczyliśmy 'zapamiętaj mnie' niszczymy ewentualnie już istniejace ciasteczko oraz tworzymy nowe
				unset($this->request->data['User']['remember_me']);
				$this->request->data['User']['password'] = $this->Auth->password($this->request->data['User']['password']);
				$this->Cookie->write('remember_me_cookie', $this->request->data['User'], true, '2 weeks');
			}
			$this->User->id = $this->Auth->user('id');
			$this->User->saveField('last_login', date('Y-m-d H:i:s')); // zapisujemy czas logowania
			$this->redirect($this->Auth->redirect()); // przekierowanie na stronę główną
		} else {
			$this->Session->setFlash('Nieprawidłowy login lub hasło'); // jeśli nie powiodło się
		}
	}
}

public function logout() {
	if ($this->Auth->loggedIn()) {
		$this->Cookie->delete('remember_me_cookie'); // niszczymy ciasteczko
		$this->redirect($this->Auth->logout()); // logout
	} else {
		$this->redirect(array('action' => 'login'));
	}
		
}

Prawda, że proste?

Widok

No i nadszedł czas na sam formularz do logowania. Tworzymy plik

/app/View/Users/login.ctp
A w nim:


<h2 class="title">Zaloguj się na swoje konto</h2>
<?php
	echo $this->Form->create('User');
	echo $this->Form->input('username');
	echo $this->Form->input('password');
	echo $this->Form->input('remember_me', array('label' => 'Zapamiętaj mnie', 'type' => 'checkbox'));
	echo $this->Form->end(array('label' => 'Zaloguj się'));
?>

Tutaj wykorzystaliśmy Form Helper, dzięki któremu tworzymy formularz zgodny z konwencjami nazewnictwa oraz automatycznie dodane zostają dane typu maxlength podane przy tworzeniu tabeli w bazie danych.

Na zakończenie

Mam nadzieje, że poradnik się komuś przyda. Jeśli coś jest mało jasne, zapraszam do dyskusji .

Pozdrawiam i dziękuję.

Wybrane dla Ciebie
Komentarze (25)