Witam. Niedawno zacząłem naukę obiektowego PHP i w ramach ćwiczeń postanowiłem zrobić system logowania. Niby wszystko działa, ale nie wiem, czy nie ma jakichś błędów i czy nie dałoby się czegoś zrobić lepiej. Moje wątpliwości dotyczą szczególnie tego:
1) czy rzeczywiście jest to standardowe rozwiązanie w OOP,
2) czy powinienem dodać wykrywanie błędów w kodzie (coś w stylu try/catch),
3) zabezpieczenia kodu (mam w zasadzie tylko htmlentities)
Nie będę może załączać całego kodu - problemy powinny być już widoczne w klasie tworzącej bazę, klasie logującej i samym pliku login.php:
DB.php:
<?php
//klasa łącząca z bazą danych
class DB{
private static $connection = null; //połączenie
public $pdo;
private $host = 'localhost', $dbname='home', $username = 'root', $password = ''; //dane bazy
private function __construct(){
//nawiązuje nowe połączenie
try{
$this->pdo = new PDO("mysql:host={$this->host};dbname={$this->dbname}", $this->username,$this->password);
} catch(PDOException $e){
die($e->getMessage());
}
}
//metoda, przez którą wykonuje się połączenie z bazą danych - zapobiega wielokrotnym połączeniom
//łączenie odbywa się więc przez DB::connection();
public static function connection(){
if(!isset(self::$connection)){
self::$connection = new DB();
}
return self::$connection;
}
public function __destruct(){
$this->pdo = null;
self::$connection = null;
}
}
Login.php:
<?php
class Login{
private $login, $password;
private $con;
public function __construct($con){
$this->con = $con->pdo;
$this->login = $_POST['login'];
$this->password = $_POST['password'];
$this->login = $this->clear($this->login);
$this->password = $this->clear($this->password);
$this->checkData();
}
//zabezpieczenie przed wpisywaniem niedozwolonych znaków
private function clear($string){
return htmlentities($string, ENT_QUOTES, 'UTF-8');
}
//jeśli puste lub zalogowany
private function checkData(){
if($this->login=='' || $this->password== ''){
header("Location: index.php");
exit();
}elseif(isset($_SESSION['username'])){
header("Location: home.php");
exit();
}
}
//załadowanie danych z bazy
public function loadData(){
$sql = "SELECT id, username, password, time, rank, info FROM users WHERE username='{$this->login}'";
$request = $this->con->prepare($sql);
$request->execute();
$num = $request->rowCount();
//jeśli jest taki użytkownik
if($num>0){
$this->setData($request);
}else{ //jeśli nie ma takiego użytkownika
$_SESSION['error'] = 'Błędny login lub hasło';
header("Location: index.php");
}
}
//logowanie
private function setData($request){
$result = $request->fetch(PDO::FETCH_ASSOC);
//weryfikacja hasła
if(password_verify($this->password, $result['password'])){
unset($_SESSION['error']);
$_SESSION['id'] = $result['id'];
$_SESSION['username'] = $result['username'];
$_SESSION['info'] = $result['info'];
$_SESSION['time'] = $result['time'];
$_SESSION['rank'] = $result['rank'];
header("Location: home.php");
}else{
$_SESSION['error'] = 'Błędny login lub hasło';
header("Location: index.php");
}
}
//wylogowanie
public static function logout(){
unset($_SESSION['id']);
unset($_SESSION['username']);
unset($_SESSION['rank']);
unset($_SESSION['info']);
unset($_SESSION['time']);
unset($_SESSION['error']);
unset($_SESSION['error_2']);
unset($_SESSION['error_change']);
header("Location: index.php");
exit();
}
}
I sam plik, do którego wędrują zmienne z POST:
<?php
require_once('init.php');
if(is_logged()){ //przekierowanie, jeśli użytkownik jest już zalogowany
header("Location: home.php");
exit();
}
$con = DB::connection();
$login = new Login($con);
$login->loadData();
$con->__destruct();
Mam jeszcze inne klasy, np. rejestrację, ale myślę, że tyle wystarczy - możliwe, że jest tu sporo błędów. Z góry dziękuję za wszelkie sugestie, jak mógłbym poprawić ten kod.