|
You last visited: Today at 08:12
Advertisement
OOP - Klassen Bsp.: User
Discussion on OOP - Klassen Bsp.: User within the Web Development forum part of the Coders Den category.
02/17/2016, 21:39
|
#1
|
elite*gold: 0
Join Date: Jul 2010
Posts: 283
Received Thanks: 16
|
OOP - Klassen Bsp.: User
Abend Com,
ich habe ein kleines großes Problem.
Da ich hauptsächlich Prozedural Programmiere ist die OOP auf der Strecke geblieben.
Mein größtes Problem ist das ich nie weiß in welchen Klasse nun welche Methoden kommen und wann ich lieber eine neue Klasse erstellen soll.
Ich bräuchte einmal eine kleine Starthilfe von euch. Im Internet sind zwar viele Beispiele leider widersprechen sie sich gerne mal. Auch denke ich bei den vielen Beispielen das man das nicht so machen sollte / besser machen kann.
Fangen wir mal an mit meinen wirren Ideen.
Ich habe die Klasse "User"
In diese Klasse gibt es Methoden wie setId, setNickname und dementsprechend auch getId ...
PHP Code:
class User {
private $iId;
private $sNickname;
private $sMail;
public function setId($iId = 0) {
if ( is_integer($iId) && $iId > 0 ) {
$this->iId = (int) $iId;
}
}
public function getId() {
return $this->iId;
}
}
Für die Datenbeschaffung aus der Datenbank gibt es eine extra Klasse.
Soweit alles gut.
Wo kommt aber nun die "Login-Verwaltung" hin? mit in die User-Klasse? oder eine eigene Klasse?
Ich selbst würde eine eigene Klasse erstellen.
Wohin kommen die Sachen hin für die Neuanlage von Usern?
checkPassword (Lang genug, genug zeichen ..)
checkNickname ...
Wieder in eine eigene Klasse?
Muss man bei der User Klasse sowas wie checkNickname vorhanden haben? Oder sollte man davon ausgehen wenn der Name in der Datenbank steht dann wird er schon in Ordnung sein.
Wie man vll. sieht ist es bei mir derzeit recht durcheinander und ich hoffe das mir hier wer weiterhelfen kann.
Mfg Masterkroko
|
|
|
02/17/2016, 22:00
|
#2
|
elite*gold: 60
Join Date: Sep 2013
Posts: 1,427
Received Thanks: 248
|
Wenn du nicht gerade mit einem Framework arbeitest, ist es dir eigentlich frei überlassen, wie du deine Klassen strukturieren willst. Vor deinem Problem stehen Viele, die gerade mit OOP anfangen. Das Prinzip von Gettern&Settern hast du ja anscheinend verstanden. Außerdem sei noch gesagt, dass du OOP und prozedurale Programmierung "mischen" kannst. Nun zu deinen Methoden: Deine Userklasse könnte z.B. so aussehen:
PHP Code:
class User { private $db; function __construct($connection) { $this->db = $connection; } public function register(...) { // Daten in Datenbank eintragen } public function login($username,$password) { // Mit Daten aus Datenbank vergleichen und ggf. die Session setzen mit z.B. der UserID } public function hasValidLogin() { if(isset($_SESSION['user'])) { return true; } }
public function logout() { session_destroy(); unset($_SESSION['user']); return true; } }
Deine index.php könnte z.B. so aussehen
PHP Code:
<?php
$connection = new mysqli(...);
$user = new User($connection);
if ($user->hasValidLogin()) { // User weiterleiten }
|
|
|
02/17/2016, 22:56
|
#3
|
elite*gold: 0
Join Date: Jul 2010
Posts: 283
Received Thanks: 16
|
Ich arbeite mit keinem Framework. Die Funktionalität der Klassen hab ich eig. drauf ich weiß halt nur nicht was man wo hin schreiben muss. Wie du schon geschrieben hast typisches Anfängerproblem.
Die Kommunikation mit der Datenbank wollte ich ja wie bereits erwähnt in eigenen Klassen auslagern. Hier verwende ich das öhm "DAO Pattern".
Ich möchte eig auch soweit wie möglich nur OOP. Natürlich wird hier und da mal ein bisschen prozedurale Programmierung auftauchen jedoch möchte ich das so gut es geht vermeiden.
Du hast jetzt alles in die User-Klasse geworfen.
Diverse Foren und Beiträge sagen z.B. das die Login-Verwaltung bei dem oberen Beispiel login, haslogin, logout gesondert in eine extra Klasse kommen sollte.
Auch stellt mir die Frage mit dem "checkNickname".
Eig darf diese Methode ja nur verwendet werden wenn ich ein neuen User anlegen.
Sobald der Name in der Datenbank steht darf man den Nickname eig nicht mehr prüfen. Ich kann ja nicht auf einmal sagen määäp dein Nickname passt nicht obwohl er schon Jahrelang den Namen hat.
Da würde in meinen Augen folgendes für die User-Klasse raus kommen:
Natürlich für jeden set die passende get Methode
PHP Code:
class User { private $iId; private $sNickname; private $sMail; private $iRights;
public function setId($iId = 0) { if ( is_integer($iId) && $iId > 0 ) { $this->iId = (int) $iId; } }
public function getId() { return $this->iId; }
public function setNickname() {}
public function setMail() {} public function setRights() {} public function checkNickname() { // min- & max-length, unerlaubte Zeichen }
public function checkPassword() { // min- & max-length, Bestimmte zeichen vorhanden? } }
und dann eine weiter Klasse für die Login-Verwaltung? Oder doch da rein wahhhh
|
|
|
02/17/2016, 23:51
|
#4
|
elite*gold: 60
Join Date: Sep 2013
Posts: 1,427
Received Thanks: 248
|
Quote:
Originally Posted by Masterkroko1
Die Kommunikation mit der Datenbank wollte ich ja wie bereits erwähnt in eigenen Klassen auslagern. Hier verwende ich das öhm "DAO Pattern".
|
Wenn ich es richtig in Erinnerung habe, benötigst du trotzdem eine User Klasse mit Userattributen. Meine Klasse würde z.b. die UserDAO Klasse darstellen, da dort die "Userfunktionen" beinhaltet sind und mit Objekten der Klasse User arbeitet.
Quote:
Originally Posted by Masterkroko1
und dann eine weiter Klasse für die Login-Verwaltung? Oder doch da rein wahhhh
|
Zur Not einfach testen. Es kristallisiert sich meistens schnell heraus, ob es sinnvoll ist
Quote:
Originally Posted by Masterkroko1
Auch stellt mir die Frage mit dem "checkNickname".
Eig darf diese Methode ja nur verwendet werden wenn ich ein neuen User anlegen.
Sobald der Name in der Datenbank steht darf man den Nickname eig nicht mehr prüfen. Ich kann ja nicht auf einmal sagen määäp dein Nickname passt nicht obwohl er schon Jahrelang den Namen hat.
|
Die Methode einfach nicht nochmal aufrufen, oder sehe ich das falsch?
|
|
|
02/17/2016, 23:56
|
#5
|
elite*gold: 0
Join Date: Apr 2011
Posts: 11,117
Received Thanks: 2,436
|
Meiner Meinung nach macht es kein Sinn register und login in den User zu tun !Mach dir eine Klasse namens(wobei der Name ja eh egal ist) UserController, dort hast du dann Methoden wie register, create, update, delete..
Diese Methoden verlangen dann ein User somit sagst du einfach UserController->register($user) und in der register klasse holst du dir die Daten aus dem User und erstellst ein(natürlich noch checks ob er schon existiert etc..).
Das ganze kannst du für alles machen z.b. ein ProductController mit den Methoden :
- create, update, delete, findById, findAll, findByProductName etc...
Ps. solltest du Methoden zum suchen wie z.b. findById haben erstell dir dann ein Repository wo du dir die Daten aus der Datenbank holst also z.b. UserRepository->findById($id) und die Methode gibt dir dann ein User wieder(Objekt).
Ps²: Schau dir mal Doctrine und Entitys an, ist praktisch
|
|
|
02/17/2016, 23:58
|
#6
|
elite*gold: 0
Join Date: May 2015
Posts: 700
Received Thanks: 444
|
Jetzt nur meine Meinung, ohne Anspruch auf Richtigkeit:
Ich würde das eindeutig trennen, denn ich sehe das typische User Objekt mit Attributen wie Name, E-Mail, Passwort ... als Ergebnis vom Authentifizierungsprozess, und nicht als daran teilnehmender Akteur. Ein Benutzer authentifiziert sich schließlich nicht selber, sondern wird authentifiziert (Passiv).
Angenommen, wir modellieren ein Forum mit OOP. Dann sind Klassen wie "Post", "Topic", "Subforum", ... vielleicht sinnvoll. Jeder Post benötigt einen Autor: Ein Objekt der Klasse User. Welchen Sinn macht nun etwa folgender Aufruf, wenn logout() wie im zweiten Beitrag implementiert wird?
Quote:
Post post = ...;
post.getAuthor().logout();
|
Der Aufruf suggeriert, dass wir den Autor vom Beitrag abmelden. Eigentlich hat das aber jetzt wirklich überhaupt nichts mit dem Autor zu tun, sondern es meldet uns selber ab. Komische Semantik.
Mit so einem Ansatz wirft man den Authentifizerungsprozess und einen Benutzer - zwei Dinge - in eine Klasse. Und das ist nicht so gut. Eher würde ich die Klasse von JWonderpig zum Beispiel in "UserManager" oder so umbenennen und dann bei "login()" ein Objekt von User zurückgeben, mit dem dann die restliche Anwendung arbeitet (also trennen).
Edit: Ich würde dir raten, etwas mit Symfony oder so zu arbeiten. Wenn man sieht, wie richtige Frameworks OOP nutzen, macht alles auf einmal super viel Sinn. Das war zumindest meine Erfahrung.
Das ist zum Beispiel ein super Entwurf für die ganze Geschichte: 
Überflieg das vielleicht mal ein bisschen.
|
|
|
02/18/2016, 00:13
|
#7
|
elite*gold: 60
Join Date: Sep 2013
Posts: 1,427
Received Thanks: 248
|
Wenn du mit Symfony den EntityManager und das ORM nutzt, kommt dein gewünschtes DAO Pattern durch Entities und Repositories zum Einsatz. Die Entities entsprechen dann den Tabellen in deiner Datenbank und die Repositories den Managerklassen, wie sie im Post über mir beschrieben wurden.
|
|
|
02/18/2016, 09:58
|
#8
|
elite*gold: 0
Join Date: Jul 2010
Posts: 283
Received Thanks: 16
|
Also würde ich dann 3 Klassen verwenden
1. Klasse nur für einen vorhanden User (id, email, nickname ...)
2. Klasse kümmert sich um den Login, Registrierung & co.
3. Klasse die nur mit der Datenbank redet (create,update,select)
PHP Code:
class User { private $iId; private $sNickname; private $sEmail;
public function setId() {} public function getId() {}
public function setNickname() {} public function getNickname() {} public function getEmail() {} ... }
PHP Code:
class UserDao { private $rDbConn;
public function __construct() {}
public function getUserById() { $oUser = new User(); // Selektiert die Daten $oUser->setNickname($row['nickname']) return $oUser; }
public function createUser() {}
public function deleteUser() {}
public function changePassword() {} }
PHP Code:
class UserController { private $sMinPassword = 5; private $sMaxPassword = 25;
public function checkPassword() {} public function login() {} public function logout() {}
public function isLoggedIn() {} }
Hier wird geprüft ob der User eingeloggt ist und selektiert dann die Userdaten.
PHP Code:
$oUserController = new UserController(); $oUserDao = new UserDao();
$iUserId = $oUserController->isLoggedIn(); $oUser = $oUserDao->getUserById($iUserId); // Vll. als 2 Parameter ein User-Objekt mitgeben falls vorhanden
Lauf ich damit "richtig" oder sollte ich es abändern?
|
|
|
02/18/2016, 21:06
|
#9
|
elite*gold: 0
Join Date: May 2015
Posts: 700
Received Thanks: 444
|
Ich finde das sinnvoll, oder sehe zumindest nicht, was dagegen spraeche.
|
|
|
02/18/2016, 23:53
|
#10
|
elite*gold: 0
Join Date: Jul 2010
Posts: 283
Received Thanks: 16
|
Danke.
Meine User-Klasse hat schon die ersten Attribute & Methoden.
Fange nun mit der UserDao-Klasse an.
Hat hier vll. noch wer eine verständliche Anleitung bezüglich Fehlerbehandlung (Exception) zur Hand? Ansonsten werde ich morgen nochmal das web danach durchsuchen. Als Beispiel hätte ich diese Methode:
PHP Code:
public function getUserById($iId = 0) {
if ( is_integer($iId) && $iId > 0 ) {
$sqlUserData = "SELECT `user_id`, `username`, `email`, `right`";
$sqlUserData .= " FROM `users`";
$sqlUserData .= " WHERE `user_id` = " . (string) $iId;
$resUserData = $this->oDbConn->query($sqlUserData);
if ( $resUserData === false ) {
throw new Exception(".....1");
}
if ( $resUserData->num_rows != 1 ) {
throw new Exception(".....2");
}
$rowUserData = $resUserData->fetch_assoc();
$oUser = new User();
$oUser->setId($rowUserData['user_id']);
$oUser->setUsername($rowUserData['username']);
$oUser->setMailAddress($rowUserData['email']);
$oUser->setRight($rowUserData['right']);
return $oUser;
}
else {
throw new Exception("....3");
}
}
|
|
|
02/19/2016, 00:19
|
#11
|
elite*gold: 0
Join Date: May 2015
Posts: 700
Received Thanks: 444
|
Lieber von Exception erben und dann eine spezifischere Exception werfen. PHP bringt auch schon ein paar von Haus aus mit, siehe 
Statt der dritten Exception könntest du zum Beispiel eine InvalidArgumentException werfen.
Oder du erbst selber von Exception, das ist für spezifische Fehler, die in deinem Code auftreten können, auch immer gut. Der Sinn dahinter ist dann, dass du auch nur spezifische Exceptions fangen kannst. Angenommen, du hast etwa eine Methode
parseXmlDocument($file) throws IOException, MalformedDocumentException, InvalidArgumentException { ... }
IOException wird geworfen, wenn die Datei nicht gelesen werden kann, MalformedDocumentException wenn die Datei kein richtiges XML enthält, InvalidArgumentException wenn null für $file übergeben wird.
Die InvalidArgumentException willst du gar nicht fangen, denn wenn die kommt, hast du einen Bug im Code. Würde die Funktion aber für jeden Fehler nur Exception werfen, könntest du nur alle Fehler oder keinen Fehler fangen. Jetzt kannst du einen catch-Block für IOExceptionen und einen für MalformedDocumentException haben, und die InvalidArgumentException einfach durchfallen lassen.
Wenn kein getUserById() keinen Benutzer findet, könntest du auch null zurück geben. Das würde ich davon abhängig machen, wie du die Methode später verwenden möchtest (dann aber auch konsistent bleiben): Rufst du die get...By...() nur auf, wenn du dir schon absolut sicher bist, dass es auch ein Ergebnis gibt? Dann wäre es irgendein Fehler, wenn es doch kein Ergebnis gibt, und eine Exception angebracht.
Wenn du die Methoden aber auch dazu verwendest möchtest, um zu prüfen, ob es ein derartiges Objekt überhaupt existiert, fände ich persönlich null besser.
Der Fall num_rows != 1 ist wieder eindeutig, wenn es mehrere Einträge mit dem selben PK gibt ist das ein Fehler und eine Exception ist angebracht.
|
|
|
02/19/2016, 09:29
|
#12
|
elite*gold: 0
Join Date: Jul 2010
Posts: 283
Received Thanks: 16
|
Das ich mit mit vererbten Exception arbeiten muss war mir bewusst.
Die oben im Beispiel angegeben Exception waren hauptsächlich da um zu zeigen wo welche zum Einsatz kommen würden.
Derzeitiger Gedanke war das die get...By...() Funktionen nur aufgerufen werden wenn der die Daten auch da sein sollten. Also im Fehlerfall mit ner exception behandeln.
Ich hab bewusst leider noch keine vererbte Exception Klasse gesehen. Deswegen weiß ich nicht genau was in so einer alles enthalten sollte / was die alles macht.
|
|
|
02/19/2016, 13:13
|
#13
|
elite*gold: 0
Join Date: May 2015
Posts: 700
Received Thanks: 444
|
Dann finde ich deinen gewaehlten Einsatz gut.
Eine eigene Exception muss gar nicht mehr koennen; es geht wirklich hauptsaechlich darum, den catch Block auf spezifischere Fehler beschraenken zu koennen.
Nebenbei: Bei privaten Methoden bietet es sich uebrigens auch an, die Argumente mit assert() statt mit einer Exception zu sichern.
|
|
|
02/19/2016, 13:40
|
#14
|
elite*gold: 0
Join Date: Jul 2010
Posts: 283
Received Thanks: 16
|
Wuat
Ich hätte da noch sowas wie Logging / automatische Fehlermail an admin & co reingehauen.
|
|
|
02/19/2016, 18:38
|
#15
|
elite*gold: 60
Join Date: Sep 2013
Posts: 1,427
Received Thanks: 248
|
Falls du Symfony nutzt, gibt es da den Monologger. Der kann auch Mails verschicken.
|
|
|
 |
|
Similar Threads
|
PHP & Klassen Login, User, Registrierung?
07/20/2014 - Web Development - 15 Replies
Ahoi Matrosen,
ich mal fragen wie ihr die Bereiche Login, User, Registrierung zusammenführt / teilt.
Habt ihr 1 große Klasse wo alles drin ist oder 3 Klassen in einem Login & Logout anderem die Registrierung dann noch die 3te Klasse (User) die die Daten aus der Datenbank beschafft? :confused:
und welche Methoden würdet ihr eventuell in die verschiedene Klassen packen?
Hab leider immer nur prozedural Programmiert und könnte auch dadrin die Themen schnell runter schreiben jedoch...
|
Welche Klassen kann man mit den Klassen von WoW vergleichen?
10/09/2011 - General Gaming Discussion - 30 Replies
Thema sagt eigentl. alles ;)
|
_TradEmArk_™ Public v.12.4 [*Weapon Binder,Kill User,Folow User,No Fog,Crosshair...*]
07/28/2011 - WarRock Hacks, Bots, Cheats & Exploits - 47 Replies
http://www.fotos-hochladen.net/uploads/nicesqnj9fr 42o.png
Status: Undetected
Download:
http://uploaded.to/file/2i9yl1mv
Virustotal:
VirusTotal - Free Online Virus, Malware and URL Scanner
|
All times are GMT +1. The time now is 08:12.
|
|