Ankündigung

Einklappen
Keine Ankündigung bisher.

OOP - Klasse spiegelt Datenbanktabelle wieder

Einklappen

Neue Werbung 2019

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

  • OOP - Klasse spiegelt Datenbanktabelle wieder

    Hallo!

    Folgendes Problem ist mir schon öfter begegenet:

    In der Datenbank liegt z.B. eine typische Tabelle "User".
    Im Quellcode gibts dann dazu eine entsprechende Klasse "User", die mit gettern und settern den Zugriff auf die Attribute wie "name" usw. ermöglicht.

    In einem Online Buch habe ich eine Klasse gefunden, die eigentlich genau so aussieht wie ich mir das vorstelle. Hier im Beispiel 2.5 zu sehen: klick
    Genauso stelle ich mir das vor. Allerdings gibts in dem Beispiel keine Möglichkeit eine neue "Person" zu erstellen und der DB hinzuzufügen.

    Wie könnte man das denn noch hinzufügen?
    Es gibt doch bestimmt noch weitere Lösungen für das Problem, weiß nur nicht so recht nach was ich da suchen soll.
    Hat da jemand ein paar Tipps für mich?

  • #2
    wenn ich mich nicht irre erzeugst du ein objekt der klasse person (in deiner beispiel klasse) indem du dem konstruktor eine id übergibst. was du augenscheinlich tun musst ist, eine noch nicht vorhandene user_id zu übergeben und dann __set('spaltenname', 'wert') ausführen. REPLACE INTO ersetzt einen eintrag bzw. legt eine neue zeile an, sofern die id noch nicht vorhanden ist.

    Kommentar


    • #3
      ok, aber welche id?

      ja das macht sinn, dann würde ja alles schon so funktionieren.
      Nur woher krieg ich eine passende id?
      die id in der datenbank tabelle ist auf auto_increment gesetzt.

      Ich hatte dran gedacht einfach einen Standard Konstruktor zu schreiben, also ohne Paramter, der dann einfach ein INSERT INTO... macht und damit dann eine neue id erzeugt die ich dann verwende. Ist das sinnvoll?

      Kommentar


      • #4
        Es gibt doch bestimmt noch weitere Lösungen für das Problem, weiß nur nicht so recht nach was ich da suchen soll.
        Such mal nach ActiveRecord und ORM.

        Kommentar


        • #5
          du kannst auch einfach den konstruktor weglassen, dann kannst du funktionen erzeugen, die zum anlegen neuer user zuständig sind und funktionen, mit denen du daten bereits vorhandener user verarbeiten kannst.

          die nächste id erhälst du mit

          PHP-Code:
          $sql "SELECT MAX(id)+1 as maximum FROM tabelle"

          Kommentar


          • #6
            meine klasse

            hab jetzt mal die klasse aus dem beispiel genommen und bisschen abgeändert.
            Wenn man im Konstruktor eine Id > 0 übergibt, werden die (hoffentlich) vorhandenen Daten aus der Datenbank geholt. Wenn eine 0 übergeben wurde handelt es sich um einen neuen Datensatz, der per setter gefüllt werden kann und erst anschliessend mit der Methode create() in der DB angelegt wird. Beim Anlegen wird mit mysql_insert_id() die verwendete id ermittelt und im Objekt gespeichert. Wenn man anschliessend mit dem Objekt arbeitet, werden die Änderungen, direkt auch in die DB geschrieben.
            Ausserdem gibts noch eine Methode delete zum Löschen...

            Durchgetestet hab ichs mal, klappt soweit.

            Kann man mit sowas sinnvoll arbeiten oder ist das totaler Schrott den ich da fabriziert habe?
            Vor allem bei der Verwendung von mysql_insert_id() ist mir irgendwie mulmig.
            Was ist gut/schlecht an meiner Klasse?


            Code:
            <?php
            require_once 'DB_MySQL.php';
            
            class Posting {
            
              private $db;
              private $id;
              private $cache = array();
              private $keys = array('title', 'text', 'date', 'author');
              private $autocommit = TRUE;
            
              public function __construct($id) {
                $this->db = new DB_MySQL;
                $this->id = $id;
                if($id==0) {
                  $this->autocommit = FALSE;
                }
              }
            
              public function __get($memberName) {
                if($memberName == 'id') {
                  return $this->id;
                }
                if(!in_array($memberName, $this->keys)) {
                  return;
                }
            
                if(!isset($this->cache[$memberName])) {
                  $this->db->query(
                    sprintf(
                      "SELECT %s
                         FROM posting 
                       WHERE id = '%d';",
            
                      $memberName,
                      $this->id
                    )
                  );
                  
                  if($row = $this->db->fetchRow()) {
                    $this->cache[$memberName] = $row['name'];
                  }
                }
            
                return $this->cache[$memberName];
              }
            
              public function __set($memberName, $value) {
                if(!in_array($memberName, $this->keys)) {
                  return;
                }
                
                if($this->autocommit) {
                  $this->db->query(sprintf("UPDATE posting 
                                                            SET %s = '%s' 
                                                            WHERE id = '%d';", $memberName, $value, $this->id));
                }
                $this->cache[$memberName] = $value;
              }
            
              public function create() {
                if($this->id>0) {
                  return;
                }
                $this->db->query(sprintf("INSERT INTO posting (author, title, text, date) 
                                            VALUES ('%s', '%s', '%s', '%s');", 
                                         $this->cache['author'],
                                         $this->cache['title'],
                                         $this->cache['text'],
                                         $this->cache['date']
                                       ));
                
                $this->id = mysql_insert_id();
                if($this->id > 0) {
                  $this->autocommit = TRUE;
                }
              }
              public function delete() {
                if($this->id>0) {
                  $this->db->query(sprintf("DELETE FROM posting 
                                                          WHERE id = '%d';", $this->id));
                }
                $this-> cache = array();
                $this->id = 0;
                $this->autocommit = FALSE;
              }
            
            }
            ?>

            Kommentar


            • #7
              Nein, ich finde das keineswegs unbrauchbar.
              Dennoch, mögliche Probleme:
              * Allgemeine Unflexibilität für komplexere Gebilde und Ineffektivität für mehrere Einträge
              * Limitierung durch deine MySQL Klasse (mysqli vielleicht die bessere Lösung?)
              Fahrlässig:
              PHP-Code:
              $this->db = new DB_MySQL;
              # sowie
              $this->id mysql_insert_id(); 
              Willst du wirklich eine neue Datenbankverbindung aufbauen? Oder was passier bei new DB_MySQL?

              Dein Verwendung der last insert id ist nicht falsch, nur insofern dass du es prozedural verwendest gegen jegliche Kapselung. Das muss in jeden Fall in Verbindung deiner Datenbankklasse aufgerufen werden.

              Deine Verwendung des Begriffs autocommit entspricht nicht der vorgegebenen und verwirrt etwas... was hast du damit eigentlich vor?

              Man merkt, dass du nicht getestet hast, dabei sollten dir noch ein paar Logik Fehler zu den Attributen auffallen, und wie bereits gesagt, performancetechnisch sind die einzelnen Updates sehr fragwürdig.


              Zitat von Asipak Beitrag anzeigen
              PHP-Code:
              $sql "SELECT MAX(id)+1 as maximum FROM tabelle"
              Sorry, das ist Mist. Das kann sehr schnell zu Fehlern des Typs Race Condition führen...

              Fazit:
              Zitat von David Beitrag anzeigen
              Such mal nach ActiveRecord und ORM.
              Stellt bereits bereit, was du brauchst und noch viel mehr, was du vielleicht mal brauchen wirst. Die Einarbeitungszeit wird sich lohnen. Die Zeit so etwas selbst zu schreiben ist enorm.

              Kommentar


              • #8
                Erstmal vielen Dank für die ausführliche Antwort.

                Zitat von Phlegma Beitrag anzeigen
                Nein, ich finde das keineswegs unbrauchbar.
                Dennoch, mögliche Probleme:
                * Allgemeine Unflexibilität für komplexere Gebilde und Ineffektivität für mehrere Einträge
                * Limitierung durch deine MySQL Klasse (mysqli vielleicht die bessere Lösung?)
                gut, damit kann ich (erstmal) leben. mysqli sollte ich mir wohl auch mal angucken...
                Fahrlässig:
                PHP-Code:
                $this->db = new DB_MySQL;
                # sowie
                $this->id mysql_insert_id(); 
                Willst du wirklich eine neue Datenbankverbindung aufbauen? Oder was passier bei new DB_MySQL?
                ja da wird eine neue DB Verbindung aufgebaut. Hab das aber erstmal eingebaut um das ganze testen zu können.
                Wie macht man sowas ordentlich? Hab schon öfters ein globales DB-Objekt gesehen. Also im gesamten Programm wird von allen Klasse ein globales DB Objekt verwendet, ist das ordentlich? Man hört ja auch immer, das man globale Variablen vermeiden soll oder ist das was anderes?

                Deine Verwendung des Begriffs autocommit entspricht nicht der vorgegebenen und verwirrt etwas... was hast du damit eigentlich vor?
                Naja ich kenn die vorgegebene Verwendung von autocommit nicht...hab ich einfach mal so genannt. Wenn autocommit == FALSE ist, dann wird eben nicht bei jedem Zugriff über die Set-Methode auch direkt in die Datenbank geschrieben. Die Änderungen finden also nur im Objekt statt und werden nicht direkt in die DB übertragen. Ich verwende das bei einem "neuen" Objekt. Wenn man ein Objekt erzeugt, was noch nicht in der DB vorhanden ist, kann man das Objekt erstmal per set-Methoden "füllen" ohne das dann schon in die DB geschrieben wird. Erst mit create() wird das Objekt dann auch in die DB geschrieben...

                Stellt bereits bereit, was du brauchst und noch viel mehr, was du vielleicht mal brauchen wirst. Die Einarbeitungszeit wird sich lohnen. Die Zeit so etwas selbst zu schreiben ist enorm.
                gut werd ich mir mal angucken...aber vll lern ich ja durch mein selbst schreiben was dazu

                Kommentar

                Lädt...
                X