Ankündigung

Einklappen
Keine Ankündigung bisher.

Umstieg auf OOP - Beziehung? (UML)

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Umstieg auf OOP - Beziehung? (UML)

    Hallo,


    ich habe bisher immer alles runterprogrammiert und so langsam glaube ich auch, dass ich zu OOP übergehen sollte. Jedenfalls versuche ich gerade Schritt für Schritt meinen Riesen-Code umzustrukturieren, nur musste ich leider feststellen, dass das doch etwas schwieriger werden könnte. Aber eins nach dem Anderen:

    Ich habe eine Klasse User, worin alle relevanten Daten (Username, Passwort, Mail,...) gegeben sind. Dazu mag ich noch eine Klasse zum Login haben, weil ich mir sagen lassen habe, dass es der Ordnung wegen besser wäre, alles so gut wie nur möglich in einzelne Dateien einzuteilen. Mein Problem ist jetzt, dass ich nicht weiß in welcher Beziehung die beiden Klassen zueinander stehen sollen. Ich versuche gerade alles über ein UML-Diagramm erstmal anzugeben, damit ich weiß wo ich anfangen soll. Ich habe mir zwar ein paar Tutorials angesehen die auch relativ leicht zu verstehen waren, nur kann ich mir speziell bei meinem Fall nicht ganz erklären, wie das aussehen soll. Dieselbe Schwierigkeit habe ich auch bei der Registrierung....

    Überhaupt frage ich mich, ob denn überhaupt eine Beziehung notwendig ist oder nicht. Dann würde mich aber auch interessieren, wie das bei der Datenbankverbindung dann gemacht werden würde, die ja eigentlich immer verwendet wird.


    LG!

  • #2
    Klassen bilden in der Regel Objekte aus der Realität ab, daher auch "Objektorientierung". Login, Logout und Registrierung sind Funktionen, welche an deinem Objekt hängen. Dies sind keine eigenständigen Klassen. Kleine Gedankenstütze: Der Benutzer meldet sich an - Benutzer->login()

    In größeren Projekten werden solche Funktionen gern in Helper-Klassen ausgelagert - der Übersicht halber.

    Beginne im ersten Schritt alle Objekte zu identifizieren, anschließend die Relationen der Objekte zueinander erfassen und danach die Funktionen zu ergänzen.

    Mit einer Übersicht der Objekte / Klassen kann man dir dann auch besser weiterhelfen.

    Kommentar


    • #3
      Hallo SirZusa,


      bedeutet dass denn dann auch, dass Dinge wie eine Userliste, Ban-System, News, Nachrichtenskript oder Chat allesamt auch nicht zu Klassen gehören sollen? So wie ich das jetzt verstanden habe, müssten das ja dann auch nur Funktionen sein, die an meinen Objekten hängen.

      Falls ja, so besteht tatsächlich das Meiste aus meinem Code nur daraus. Da wäre es mir wichtiger das erstmal entsprechend zu strukturieren (passende Verzeichnisse etc.). Gibt es denn da eine empfehlenswerte Vorgehensweise?


      LG!

      Kommentar


      • #4
        Objekte welche ich aus deiner kurzen Beschreibung erkenne und in eigene Klassen gehören:
        - Benutzer (Funktionen: login, logout, register, create, delete)
        - Newseintrag (ein einzelner Eintrag)
        - Nachricht (eine Nachricht mit Feldern... Text, Uhrzeit, Benutzer-ID, ...)
        - Chat (eine Sammlung von Nachrichten mit diversen Funktionen, z. Bsp. addNachricht(), getNewest(10) )

        Die Kunst liegt darin diese sinnvoll zu wählen und ist stark abhängig von der Architektur und dem Framework.
        Listen können auch Objekte sein (z. Bsp. eine Liste von Nachrichten)

        Es existiert sicher eine Datenbnk? Ein erster Anhaltspunkt wäre: Jede Tabelle ist eine Klasse, jede Zeile darin ein Objekt.

        Für Klassen sollte man einen Unterordner verwenden. ".../classes/"

        In der Datei wo das Objekt benötigt wird dann (Pseudocode - ungetestet)
        PHP-Code:
        require  __DIR__ 'classes/benutzer.php';
        $neuerNutzer = new Benutzer();
        $neuerNutzer->name 'name';
        $neuerNutzer->save(); 
        Ein Beispiel mit Nachrichten im Chat wäre besser gewesen - es ist aber auch schon spät. Morgen gern mehr

        Kommentar


        • #5
          Ich bin gerade am überlegen, ob vielleicht diese von dir angesprochenen Helper-Klassen was für mich in meinem Fall wären oder nicht, da ich mir vorstellen kann, dass bspw. mein Login zusammen mit den anderen Funktionen ziemlich lang werden könnte. Vielleicht magst du ja einen Blick auf meine Login-Klasse werfen (die ich ursprünglich vorhatte so zu machen)? Wäre es da denn noch wirklich angebracht, das alles in eine Funktion zur Benutzer-Klasse einzufügen? Oder habe ich hier etwas falsch/unsauber gemacht, sodass der Eindruck entsteht, es müsse in eine andere Datei nochmal einzeln rein?

          PHP-Code:
          <?php
          class Login {
            private 
          $db;

            private 
          $usernameeingabe;
            private 
          $passworteingabe;

            private 
          $id;
            private 
          $username;
            private 
          $passwort;
            private 
          $ip;
            private 
          $banstufe;    

            private 
          $gebannt_userid;
            private 
          $gebannt_ip;
            private 
          $gebannt_dauer;

            public function 
          __construct($db) {
              
          $this->db $db;

              
          $this->usernameeingabe sichern($this->db$_POST['username']);
              
          $this->passworteingabe md5(sichern($this->db$_POST['passwort']));
              
          $this->ip $_SERVER['REMOTE_ADDR'];
            }

            public function 
          login() {
              if(
          $this->userexist_check()) {      
                if(
          $this->passwortgleich_check()) {
                  if(!
          $this->gebannt_check()) {
                    
          $this->einloggen();
                    echo 
          "Erfolgreich eingeloggt. <a href='index.php'>Zum Spiel</a>."
                  }
                  else {
                    echo 
          "Nutzer wurde gesperrt.";
                  }
                }
                else {
                  echo 
          "Passwort ist falsch.";
                }
              }
              else {
                echo 
          "User existiert nicht.";
              }
            }

            private function 
          userexist_check() {
              
          $auswahl "SELECT id, username, passwort, banstufe FROM user WHERE username = '$this->usernameeingabe' LIMIT 1";
              
          $befehl mysqli_query($this->db$auswahl) or die(mysqli_error($this->db));
              
          $row mysqli_fetch_object($befehl);

              if(
          mysqli_num_rows($befehl) == 1) {
                
          $this->username $row->username;
                
          $this->passwort $row->passwort;
                
          $this->id $row->id;
                
          $this->banstufe $row->banstufe;
                return 
          true;
              }
              else {
                return 
          false;
              }
            }

            private function 
          passwortgleich_check() {
              if(
          $this->passwort == $this->passworteingabe) {
                return 
          true;
              }
              else {
                return 
          false;
              }
            }

            private function 
          gebannt_check() {
              if(
          $this->banstufe != 3) {
                
          //Wurde User bzw. IP gebannt?
                
          $abfrage "SELECT userid, ip, dauer FROM gebannt WHERE userid = '$this->id' OR ip = '$this->ip' LIMIT 1";
                
          $befehl mysqli_query($this->db$abfrage) or die(mysqli_error($this->db));

                if(
          mysqli_num_rows($befehl) == 1) {
                  
          $bann_ende_check mysqli_fetch_object($befehl);                  //Zur Kontrolle ob Bann-Zeit zu Ende gegangen ist oder nicht
                  
          $zeit date("Y-m-d H:i:s");

                  
          $this->gebannt_userid $bann_ende_check->userid;
                  
          $this->gebannt_ip $bann_ende_check->ip;
                  
          $this->gebannt_dauer $bann_ende_check->dauer;

                  
          //Ist der User immer noch gebannt/permanent gebannt?
                  
          if($this->gebannt_dauer $zeit OR $this->gebannt_dauer == "Perma") {
                    
          $this->multis_bannen();
                    return 
          true;
                  }
                  else {
                    
          $this->ban_delete();
                    return 
          false;
                  }
                }
                else {
                  return 
          false;
                }
              }
              else {
                
          $this->perma_bannen();
                return 
          true;
              }      
            }

            private function 
          multis_bannen() {
              if(
          $this->gebannt_userid != $this->id AND $this->gebannt_ip == $this->ip) {
                
          //Banne User
                
          $bannen "UPDATE gebannt SET dauer='Perma', Grund='Multi' WHERE ip='$this->ip'";
                
          $befehl mysqli_query($this->db$bannen) or die(mysqli_error($this->db));

                
          $bannen2 "INSERT INTO gebannt(userid, ip, dauer, grund) VALUES('$this->id', '$this->gebannt_ip', 'Perma', 'Multi')";
                
          $befehl2 mysqli_query($this->db$bannen2) or die(mysqli_error($this->db));

                
          $banstufe_aendern "UPDATE user SET banstufe='3' WHERE ip='$this->ip' OR id='$this->id'";
                
          $banstufe_aendern_befehl mysqli_query($this->db$banstufe_aendern) or die(mysqli_error($this->db));
              }
            }

            private function 
          ban_delete() {
              
          //Ist Bann-Zeit zu Ende soll der Eintrag entfernt werden
                
          $ban_eintrag_entfernen "DELETE from gebannt WHERE userid = '$this->id'";
                
          $ban_eintrag_entfernen_befehl mysqli_query($this->db$ban_eintrag_entfernen) or die(mysqli_error($this->db));
            }

            private function 
          perma_bannen() {
              
          //Kontrollieren, ob der User mit Perma-Ban auch in der gebannt-Liste vorzufinden ist oder nicht.. wenn nicht, eintragen
              
          $abfrage "SELECT userid, ip, dauer FROM gebannt WHERE userid = '$this->id' OR ip = '$this->ip'";
              
          $befehl mysqli_query($this->db$abfrage) or die(mysqli_error($this->db));

              if(
          mysqli_num_rows($befehl) == 0) {
                
          $ban "INSERT INTO gebannt(userid, ip, dauer, grund) VALUES('$this->id', '$this->ip', 'Perma', 'Multi')";
                
          $ban_befehl mysqli_query($this->db$ban) or die(mysqli_error($this->db));
              }
            }

            private function 
          einloggen() {
              
          $_SESSION['userid'] = $this->id;
              
          $_SESSION['username'] = $this->username;

              
          $ip_eintragen "UPDATE user SET ip = '$this->ip' WHERE id = '$this->id'";
              
          $ip_eintragen_befehl mysqli_query($this->db$ip_eintragen) or die(mysqli_error($this->db));
            }
          }
          ?>
          Dazu sei noch gesagt, dass ich mir bei der Klasse noch nicht viele Gedanken zu einer richtigen Struktur gemacht habe, sondern erstmal beim Login nur "anfangen" wollte.


          LG!

          Kommentar


          • #6
            Ich habe mal einen ersten Ansatz aus deiner Klasse generiert. Im Mittelpunkt steht der Nutzer (das Objekt). Ich habe es etwas bereinigt um das Beispiel einfach zu halten.

            Folgende Annahmen: Der Nutzer hat die die Login-Seite aufgerufen und seine Daten bereits eingegeben. ($_POST gefüllt)
            Wenn wir starten haben wir noch nichts. Ergo müssen wir im ersten Schritt prüfen ob der Benutzer überhaupt existiert und wenn er existiert laden wir auch gleich seine Daten.
            Dies passiert mit getByName(). Die Funktion gibt "null" zurück wenn kein entsprechender Nutzer gefunden wurde - so können wir auch gleich prüfen ob er existiert - andernfalsl das Benutzerobjekt das wir benötigen.
            Anschließend prüfen wir mit den Funktionen isBanned() und checkPasswort() ob er autorisiert werden darf.
            Sind die Prüfungen OK rufen wir die Funktion login() auf um die Anmeldung durchzuführen.

            Nächste Schritte:
            Die Prüfungen in die login()-Funktion verlagern.
            Wenn eine Prüfung fehlschlägt mit return "Fehlermeldung" direkt abbrechen. -> Damit musst du nicht mehr so tief verschachteln und der Code wird leichter lesbar.

            Empfehlenswert wäre ein kleines ORM / eine Persistenzschicht. Diese sorgt für das Laden und Speichern des Objektes aus/in der DB. Aber das wäre gleich etwas zu viel für den Einstieg.

            Edit: Oben die Klasse, unten der Aufruf (alles ungetestet)

            PHP-Code:
            <?php

            class Benutzer
            {
              
            // Hier die DB-Felder
              
            private $id;
              private 
            $username;
              private 
            $passwort;
              private 
            $ip;
              private 
            $banstufe;

              private 
            $db;

              public function 
            __construct()
              {
                
            $this->db DB::getInstance();
              }

              public static 
            getByName($username)
              {
                
            $db DB::getInstance();

                
            // TODO: Achtung - evtl. Injection möglich
                
            $auswahl "SELECT id, username, passwort, banstufe FROM user WHERE username = '$this->usernameeingabe' LIMIT 1";
                
            $befehl mysqli_query($db$auswahl) or die(mysqli_error($db));

                if (
            mysqli_num_rows($befehl) == 1)
                {
                  
            $benutzer = new Benutzer();

                  
            $row mysqli_fetch_object($befehl);

                  
            $benutzer->id $row->id;
                  
            $benutzer->username $row->username;
                  
            $benutzer->passwort $row->passwort;
                  
            $benutzer->ip $row->ip;
                  
            $benutzer->banstufe $row->banstufe;

                  return 
            $benutzer;
                }
                else
                {
                  return 
            null;
                }
              }

              private function 
            checkPasswort($passworteingabe)
              {
                if (
            $this->passwort === $passworteingabe)
                {
                  return 
            true;
                }
                else
                {
                  return 
            false;
                }
              }

              private function 
            login()
              {
                
            $_SESSION['userid'] = $this->id;
                
            $_SESSION['username'] = $this->username;
                
            $this->ip $_SERVER['REMOTE_ADDR'];

                
            $ip_eintragen "UPDATE user SET ip = '$this->ip' WHERE id = '$this->id'";
                
            $ip_eintragen_befehl mysqli_query($this->db$ip_eintragen) or die(mysqli_error
                  
            ($this->db));
              }
            }

            /**********************************************************************************************/

            $Benutzer getByName(sichern($db$_POST['username']));

            if (empty(
            $Benutzer))
            {
              echo 
            "User existiert nicht.";
            }
            else
            {
              
            // TODO: if ($Benutzer->isBanned) { /* ... */ }

              
            if (!$Benutzer->checkPasswort(md5(sichern($db$_POST['passwort']))))
              {
                echo 
            "Passwort ist falsch.";
              }
              else
              {
                
            $Benutzer->login();
              }
            }

            ?>

            Kommentar

            Lädt...
            X