• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Ocena kodu napisanego obiektowo

VPS Starter Arubacloud
0 głosów
299 wizyt
pytanie zadane 7 listopada 2017 w PHP przez `Krzychuu Stary wyjadacz (13,940 p.)

Witam

To znowu ja :D, po ostatnim moim poście z ocena skryptu logowania postanowiłem poszukać jeszcze w internecie informacji jak dobrze pisać obiektowo, jak na razie nie pisałem jeszcze ze wzorcem projektowym postanowiłem napisać w czystym OOP, poczytałem też o zasadzie SOLID, myślę że chociaż trochę z tego skorzystałem, ale mam 1 wątpliwość co do zasady w której kod powinien być "otwarta na rozbudowe i zamknięta na modyfikacje" czy do tego zalicza się dodanie odwołania do wykonana funkcji w już istniejącej i np. chciałbym dodać do metody verification skrypt który zablokuje konto jeżeli ktoś wpisze 4 razy błędne hasło, i dodam samo odwołanie $this->funkcja(); to złamie wtedy zasadę "open/close principle"?

DBmanager.php

<?php

class DBmanager
{
	private $db_host = "localhost";
	private $db_user = "root";
	private $db_password = "";
	private $db_name;
	private $db_connect;
	
	public function __construct($db_name = "test")
	{
		$this->db_connect = new mysqli($this->db_host, $this->db_user, $this->db_password, "$db_name");
	}
	
	public function checkConnection()
	{
		if($this->db_connect->connect_errno)
		{
			throw new Exception($this->db_connect->connect_errno);
		}
		else
		{
			return $this->db_connect;
		}
	}
		
	public function closeConnection($connect)
	{
		$connect->close();
	}
}

?>

AuthC.php

<?php

class AuthC
{		
	private $login;
	private $password;
	private $password2;
			
	public function login($login, $password)
	{		
		$this->login = htmlentities($login);
		$this->password = htmlentities($password);
		$vlogin = new VerificationLogin();
		
		try
		{
			return $vlogin->verification($this->login, $this->password);		
		}
		catch(Exception $e)
		{
			$_SESSION['exceptionLogin'] = $e->getMessage();
			return DATABASE_ERROR;
		}
	}
}

?>

VerificationLogin.php

<?php

class VerificationLogin
{
	private $login;
	private $password;
	private $DBmanager;
		
	public function __construct()
	{
		$this->DBmanager = new DBmanager();
	}
		
	public function verification($login, $password)
	{
		$connect = $this->DBmanager->checkConnection();
		
		$this->login = $connect->real_escape_string($login);
		$this->password = $password;
		
		$query = $connect->query("SELECT id, login, password, last_login FROM users WHERE login='$this->login'");
		
		if($query->num_rows >= 1)
		{
			$row = $query->fetch_assoc();
		
			if(password_verify($this->password, $row['password']))
			{
				$_SESSION['logged'] = true;
				$_SESSION['idUser'] = $row['id'];
				$_SESSION['login'] = $row['login'];
				$_SESSION['lastLogin'] = $row['last_login'];
				return LOGIN_SUCCESS;
			}
			else
			{
				$_SESSION['rememberLogin'] = $this->login; 
				$_SESSION['viewPasswordError'] = true;
				return false;
			}
		}
		else
		{
			return LOGIN_FAILED;
		}
		
		$this->DBmanager->closeConnection($connect);	
	}
}

?>

index.php

session_start();
require_once('class/ClassLoader.php');
require_once('constants.php');
$AuthC = new AuthC();

if(isset($_POST['login']))
{
	if((empty($_POST['login'])) || (empty($_POST['password'])))
	{
		$_SESSION['viewLoginError'] = true;
		$_SESSION['viewPasswordError'] = true;
	}
	else
	{
		switch($AuthC->login($_POST['login'], $_POST['password']))
		{
			case LOGIN_SUCCESS:
				header('Location: templates/informations.php');
				break;
			case LOGIN_FAILED:
				$_SESSION['viewLoginError'] = true;
				break;
			case DATABASE_ERROR:
				$_SESSION['viewExceptionLogin'] = true;
				break;
		}
	}
}

 

1
komentarz 7 listopada 2017 przez rot18ru Bywalec (2,100 p.)
Blokowanie konta powinno odbywać się w tej klasie, w której jest zmienna licząca ilość prób logowania. Problem w tym, że u ciebie wszystkie istotne informację są  w SESSION i nie da się tego całkowicie wyeliminować ( taka ułomność PHP). W dobrym programie obiektowym takie niskopoziomowe struktury powinny być opakowane w klasy bardziej bliższe dziedzinie. U ciebie dane sesji związane z logowaniem są opakowane klasą VerificationLogin. Ponieważ licznik prób logowania również jest związany z logowaniem to również powinien się znaleźć w tej klasie i tam powinno właśnie odbywać się blokowanie konta. Pamiętaj tylko, że gdy w jednej klasie używasz np. "$_SESSION['logged']" to nie możesz użyć tego wywołania w żadnej innej klasie. Jedna klasa powinna opakowywać dane związane z logowaniem, a gdy inne klasy potrzebują informacji o logowaniu, powinny użyć klasy opakowującej. Pamiętaj również, że zasady SOLID służą do redukowania złożoności programu. Jeśli jakaś zasada powoduje większą złożoność to nie należy jej w tym wypadku przestrzegać. Nie powinieneś myśleć w kategoriach "czy ten kod przestrzega SOLID", ale "czy ten kod da się jakoś uprościć".
komentarz 7 listopada 2017 przez `Krzychuu Stary wyjadacz (13,940 p.)
myślałem żeby ten skrypt zrobić w ten sposób: stworzyć nową metodę w klasie VerificationLogin i wywołać ją jeśli ktoś wpisze błędne hasło i przy każdej próbie dodawać +1 do liczby która zostaje zapisana w bazie a gdy zaloguje się to wyzerować ten licznik, a w miarę dobrze ten skrypt wygląda?

2 odpowiedzi

+1 głos
odpowiedź 7 listopada 2017 przez ProgramistaStepek Nałogowiec (27,020 p.)

PHP to nie do końca moja bajka, ale z tego co widzę to mógłbyś pokusić się o użycie interfejsów oraz wzorców projektowych np. Dependency Injection w tym miejscu:

public function __construct()
    {
        $this->DBmanager = new DBmanager();
    }

Szczegóły pozostawiam do zbadanie Tobie.

komentarz 7 listopada 2017 przez `Krzychuu Stary wyjadacz (13,940 p.)
na początku chciałem użyć bez zobaczyć jak to będzie działało.
1
komentarz 7 listopada 2017 przez ProgramistaStepek Nałogowiec (27,020 p.)
Poprosiłeś o ocenę, więc napisałem tyle ile wiem :) Druga sprawa, że dopiero teraz doczytałem, że chciałeś to na początku zrobić bez wzorców. W takim razie proponuję użycie PDO przy połączeniu, jako początkowe ulepszenie twojego skryptu.
komentarz 7 listopada 2017 przez `Krzychuu Stary wyjadacz (13,940 p.)
jestem w trakcie uczenia się PDO, w między czasie tworzyłem skrypt z wykorzystaniem MySQLI
0 głosów
odpowiedź 11 listopada 2017 przez `Krzychuu Stary wyjadacz (13,940 p.)
ref

Podobne pytania

+1 głos
3 odpowiedzi 305 wizyt
pytanie zadane 15 sierpnia 2019 w C# przez luna22 Obywatel (1,420 p.)
+1 głos
3 odpowiedzi 355 wizyt
pytanie zadane 25 października 2017 w PHP przez `Krzychuu Stary wyjadacz (13,940 p.)
0 głosów
3 odpowiedzi 390 wizyt
pytanie zadane 16 stycznia 2019 w Python przez niezalogowany

92,453 zapytań

141,262 odpowiedzi

319,086 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...