Datenbank Klasse

B

Bgag

Abend!
Ich habe eine kleine Datenbank-Klasse geschrieben und hätte gern ein kleines Feedback. Ist das so gut oder ok? Was kann man noch ändern? Was kann man noch verbessern oder hinzufügen?

PHP:
<?php

class DbConnector {

    /* DATABASE VARIABLES */
    var $host = "localhost";
    var $user = "user";  
    var $password = "pwd";
    var $dbname = "dbname"; 
        
    /* VARIABLES */
    var $result;
    var $theQuery;
    var $link;
    var $result_number;
    var $db_status = "disconnected";
     var $errormessage = "";
     var $errornumber = "";
    
    /* CATCH DATABASE VARS */
    function DbConnector($host,$user,$pw,$dbname) {
    
          $this->host = $host;
          $this->user = $user;
          $this->password = $pw;
          $this->dbname = $dbname;
          $this->db_open();
    
    }
    
    /* CONNECT TO DATABASE */
    function db_open() {
        
        if($this->db_status != "connected") {
        
            if(!($this->link = mysql_connect($this->host, $this->user, $this->password))) {
                $this->db_status = "disconnected";
                $this->errormessage .= mysql_error() ."\n";
                $this->errornumber  .= mysql_errno() ."\n";
                $this->password = "******";
                return 0;
            }
            
            else {
                $this->db_status = "connected";
                $this->db_select_db($this->dbname);
                $this->password = "******";
                return 1;
            }
        }
        
        else {
            echo "Critical ERROR: You opened DB 2 times";
            $this->password = "******";
            return 0;
        }
    
    }
    
    /* SELCT DATABASE */
    function db_select_db($dbname) {
    
        if($this->db_status == "connected") {
        
            if(!mysql_select_db($dbname)) {
                $this->errormessage .= mysql_error() ."\n";
                $this->errornumber  .= mysql_errno() ."\n";
                return 0;
            }
               
               else  return 1;
        }
        
        else  return 0;
    }
    
    /* CHECK CONNECTION */
    function is_connected() {
           return($this->db_status == "connected");
    }
    
    /* EXECUTE DATABASE QUERY */
    function db_query($query) {
    
        $this->theQuery=$query;
        if($this->db_status == "connected") {
        
            if(!$this->result = mysql_query($query)) {
                $this->errormessage .= mysql_error() ."\n";
                $this->errornumber  .= mysql_errno() ."\n";
                return 0;
            }
            
            else {
                $query = trim($query);
                if(substr(strtoupper($query), 0, 4) == "SELE") $this->result_number = mysql_num_rows($this->result);
                return 1;
            }
        }
        
        else return 0;
    }
    
    /* RETURNS LATEST DATABASE QUERY */
    function getQuery() {
        return $this->theQuery;
    }
    
    /* RETURN ROW COUNT */
    function getNumRows($result){
        return mysql_num_rows($result);
    }
    
    /* GET ARRAY OF QUERY RESULTS */
    function db_save_results($typ = 0) {
    
        $array = array();
        while ($result = $this->db_get_next_result($typ)) $array[] = $result;
        return $array;
    }
    
    /* GET NEXT RESULT OF LAST QUERY */        
    function db_get_next_result($typ = 0) {

        if(!$this->result) {
            $this->errormessage .= "Result is empty.\n";
            $this->errornumber  .= 99 ."\n";
            return 0;
        }
       
        else {
            if($typ == 0) return mysql_fetch_array($this->result);
            if($typ == 1) return mysql_fetch_row  ($this->result);
            if($typ == 2) return mysql_fetch_assoc($this->result);
        }
    }
    
    /* GET LAST ERRORS */
    function db_get_last_error() {
        
        if($this->errornumber != "" || $this->errormessage != "")
        return ($this->errornumber . " : " . $this->errormessage);
        else return "";
    }
    
    /* CLOSE CONNECTION */
    function close() {
    
        if($this->db_status == "connected") {
        
            if(!mysql_close($this->link)) {
                $this->errornumber  .= mysql_errno() ."\n";
                $this->errormessage .= mysql_error() ."\n";
                $this->password = "******";
                return 0;
            }
            
            else {
                $this->db_status = "disconnected";
                $this->password = "******";
                return 1;
            }
           }
           
           else {
            $this->password = "******";
            return 0;
        }
    
    }

}
?>

Wäre euch für eure Hilfe dankbar!

MfG, Andy
 
Zuletzt bearbeitet von einem Moderator:
Also, einige Fragen, die ich mal so einwerfe:
  • Was bringt dir diese Datenbank Klasse?
  • Ist sie nur zur Übung geschrieben worden?
  • Oder soll sie im Produktiveinsatz eingesetzt werden?
  • Warum nicht in PHP5?

Dann noch eine Codetechnische Frage:

PHP:
$this->errormessage .= "Result is empty." ."\n";

Warum benutzt du hier eine Stringverkettung? Die ist langsam und frisst dir wertvolle Rechenzeit. Es ist nicht viel Rechenzeit, aber es kann viel werden, bei vielen simultanten Aufrufen.
 
Abend!
Was bringt mir diese Klasse?
  • ich kann sie in anderen klassen verwenden
  • sie spart tipparbeit
  • sie ist multibel einsetzbar

Eigentlich ist sie nicht zur Übung geschrieben worden, sondern um sie in verschiedenen Projekten Onlinegames, CMS, etc. einsetzen zu können. SO ist sie einerseits Übung und soll aber andererseits auf jeden Fall im Produktiveinsatz angewand werden.

Was schlägst du denn statt einer Stringverkettung vor? Mir ist nichts anderes eingefallen. Vorschlag?
MfG, Andy
 
PHP:
$this->errormessage .= "Result is empty.\n";

War nur die zweite Verkettung gemeint.

Ich spreche jetzt als Programmierer, der als Vorgabe bekommt diese Klasse zu benutzen, nicht als Kritiker.
Was mich stören würde:

Nebensächliche Dinge:
- Ich kann keinen Port angeben (nicht alle Datenbanken laufen auf 3306)
- Warum darf ich keine 2 parallele Verbindungen in deiner Klasse laufen lassen?
- Wahrscheinlich aus Testzwecken wird in der Methode db_query() mysql_error() direkt ausgegeben.

Wichtige Dinge:
- Falls ich mal einige MySQL Funktion nutzen möchte, die nicht in deiner Klasse vorkommt, habe ich keine Möglichkeit an die Verbindungsressource heranzukommen.
- Man hat keine Möglichkeit auf eine persistente Verbindung
- Du gibst keinerlei Methoden zur Stringmaskierung zur Hand, obwohl diese sehr essentiell sind gerade für Datenbanken (Stichwort SQL Injektionen)
- Warum überschreibst du, wenn ein Fehler auftritt, das Passwort?

PHP:
else {
                $query = trim($query);
                if(substr(strtoupper($query), 0, 4) == "SELE") $this->result_number = mysql_num_rows($this->result);
                return 1;
            }
Hier könntest du [phpf]mysql_affected_rows[/phpf] einsetzen, dadurch kannst du für alle Typen sagen, wieviele Datensätze beeinflusst wurden.
 
Abend!
Ich verstehe nicht, warum man nicht einen anderen Port nutzen kann. Man muss in $host statt nur localhost, localhost : port speichern. Das ist alles.

Ich verhindere aus SIcherheitsgründen, dass zwei Verbindungen gleichzeitig laufen. Das ist auch für den Nutzer sehr angenehm, denn so können auch unnutze Mehrfacheintäge verhindert werden.

Aus Testzwecken wurde in der funktion db_query() mysql_error() direkt ausgegeben.

Wichtige Dinge:
Felix Jacobi hat gesagt.:
Falls ich mal einige MySQL Funktion nutzen möchte, die nicht in deiner Klasse vorkommt, habe ich keine Möglichkeit an die Verbindungsressource heranzukommen.

Felix Jacobi hat gesagt.:
Man hat keine Möglichkeit auf eine persistente Verbindung
Werde ich nachrüsten und dann hier im ersten Beitrag ändern.

- Du gibst keinerlei Methoden zur Stringmaskierung zur Hand, obwohl diese sehr essentiell sind gerade für Datenbanken (Stichwort SQL Injektionen)

Felix Jacobi hat gesagt.:
Warum überschreibst du, wenn ein Fehler auftritt, das Passwort?
Aus Sicherheitsgründen.

Felix Jacobi hat gesagt.:
Hier könntest du mysql_affected_rows() einsetzen, dadurch kannst du für alle Typen sagen, wieviele Datensätze beeinflusst wurden.
Also so?
PHP:
else {
                $query = trim($query);
                if(substr(strtoupper($query), 0, 4) == "SELE") $this->result_number = mysql_affected_rows($this->result);
                return 1;
            }
MfG, Andy
 
Zuletzt bearbeitet von einem Moderator:
PHP:
if(substr(strtoupper($query), 0, 4) == "SELE") $this->result_number = mysql_affected_rows($this->result);

Einfach zu:

PHP:
$this->result_number = mysql_affected_rows($this->result);

Dadurch hast du bei Updates die Anzahl der geänderten Spalten, bei Selects die Zahl der gewählten Spalten und bei Inserts und Deletes ebenfalls.


/edit:

Und sorry wegen dem Port, ich war in Gedanken bei mysqli, wo der Port getrennt angegeben wird.
 
Abend!
Wie kann ich es denn ermöglichen, bzw. welche Änderungen muss ich vornehemen, damit man an den Verbindungsressource herankommt, um auch andere Funktionen zu nutzen?

Irgendjemand_1 hat gesagt.:
Möchtest du mir damit sagen, dass ich das auch so schreiben könnte?
PHP:
$this->result_number = mysql_affected_rows();
Also das $this->result weglassen könnte?
MfG, Andy
 
Zuletzt bearbeitet von einem Moderator:
Abend!
Wie kann ich es denn ermöglichen, bzw. welche Änderungen muss ich vornehemen, damit man an den Verbindungsressource herankommt, um auch andere Funktionen zu nutzen?


Möchtest du mir damit sagen, dass ich das auch so schreiben könnte?
PHP:
$this->result_number = mysql_affected_rows();
Also das $this->result weglassen könnte?
MfG, Andy

KANNST du schon, aber das wollte ich damit nicht sagen ;) Wobei mir da gerade auffällt, dass $this->result als Argument sowieso schonmal fehl am Platz ist. Im Prinzip brauchst du kein Argument für die Funktion aber besser ist's (für den Fall, dass du doch nochmal mehrere Verbindungen hast) ;)
Aber wenn du schon ein Argument nimmst, dann auch das richtige. Schau mal:
Code:
int mysql_affected_rows ( [resource $ Verbindungs-Kennung ] )
Du brauchst die Verbindungs-Kennung nicht das Ergebnis der Abfrage (resource $ Ergebnis würde dann das Argument heißen).
Nunja, was ich eigentlich sagen wollte:
Anmerkung: Benutzen Sie UPDATE wird MySQL keine Spalten aktualisieren, bei denen der neue dem alten Wert entpspricht. Das kann dazu führen, dass mysql_affected_rows() nicht die tatsächliche Anzahl der betroffenen Zeilen liefert, sondern nur die, die wörtlich durch die Anfrage betroffen sind.

Diese Funktion arbeitet nicht in Verbindung mit SELECT-Anfragen, sondern nur bei Anweisungen, die Datensätze verändern. Um die Anzahl der gelieferten Datensätze einer SELECT-Anfrage zu erhalten, benutzen Sie die Funktion mysql_num_rows().
Lesen, mein Freund ;)

Edit: Ich wollte auch noch
War die letzte Anfrage ein DELETE-Anweisung ohne WHERE Bedingung, wurden alle Datensätze aus der Tabelle gelöscht. Diese Funktion wird aber trotzdem Null (0) zurückliefern.
zitieren.
PHP hat nicht umsonst eine so ausgezeichnete Referenz ;) Man sollte sie auch ab und zu mal nutzen.
Achja, die Klasse an sich hab ich mir noch nicht so richtig angeschaut, aber du kannst sie ja mal mit einer der unzähligen anderen Klassen im Internet vergleichen.
 
Zuletzt bearbeitet:
Abend!
Irgendwie steh ich grade vollkommen auf dem schlauch. :suspekt:
ALso so jetzt?
PHP:
$this->result_number = mysql_affected_rows( $this->link);
MfG, Andy
 
Zurück