PHP5 MySQL Klasse

walle_89

Mitglied
Mahlzeit!
Ich baue gerade an einer eigenen MySQL-Klasse herum. Bin auch soweit fertig, wollte mich nur mal erkundigen, ob dies denn auch nach den OOP Konventionen Sinn macht und vorallem ein wenig gegen SQL-Injections gesichert ist?
Zuerst die Klasse selbst
PHP:
<?php

/**
 * MySQL-Class
 * --------------
 * Diese Klasse stellt alle nötigen Methode,
 * um auf die Datenbank zugreifen zu können.
 */

/* Fehleranzeige aktivieren */
error_reporting(E_ALL);

include('config.inc.php');

class MySQL
{
	private $connection;
	private $query;
	private $result;

	/*
	 * Konstruktormethode
	 * ------------------
	 * Stellt eine Verbindung mit dem
	 * MySQL-Server her und stellt den
	 * Charset auf UTF-8.
	 */
	public function __construct()
	{
		$this->connection = @mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD);
		if(!$this->connection)
			throw new Exception("Couldn't connect to '".MYSQL_HOST."'.");
		$database = @mysql_select_db(MYSQL_DATABASE, $this->connection);
		if(!$database)
			throw new Exception("Couldn't connect to the database '".MYSQL_DATABASE."'.");
		/* Setzt den Standardzeichensatz für die angegebene Verbindung */
		mysql_set_charset('UTF8', $this->connection);
	}

	/*
	 * Prepare-Methode
	 * ---------------
	 * Bereitet den Query-String zum Ausführen vor. 
	 * Dieser beinhaltet die für vsprintf vordefinierte
	 * Zeichenkette.
	 * @param $query Vordefinierte Zeichenkette
	 */
	public function prepare($query)
	{
		$this->query = $query;
	}

	/*
	 * Execute-Methode
	 * ---------------
	 * Führt den angegebenen MySQL-Befehl aus. 
	 * Davor werden (falls in der Zeichenkette vorhanden) 
	 * die Argumente durch die Variablen aus dem Array ersetzt.
	 * Falls keine Variablen gesetzt wurden, wird der Befehl 
	 * einfach ausgeführt.
	 * @param $query Ein Array, welches die benötigten Variablen enthält.
	 */
	public function execute($query = null)
	{
		if(is_null($query))
		{
			$this->result = @mysql_query($this->query);
		}
	    else
	    {
	    	$query			= explode(",", $query);
    		$secureSQL		= vsprintf($this->query, $query);
		$this->result	        = @mysql_query($secureSQL);
	    }
		if(!$this->result) throw new Exception(mysql_error($this->connection));
	}

	/*
	 * Fetch-Assoc-Methode
	 * -------------------
	 * Liefert ein assoziatives Array, das den ausgelesenen Datensatz enthält. 
	 * Sind keine weiteren Datensätze vorhanden gibt diese Funktion FALSE zurück. 
	 */
	public function fetch_assoc()
	{
		return mysql_fetch_assoc($this->result);
	}

	/*
	 * Fetch-Array-Methode
	 * -------------------
	 * Liefert ein Array das dem aktuellen Datensatz entspricht oder FALSE, wenn
	 * keine weiteren Datensätze vorliegen.
	 */
	public function fetch_array()
	{
		return mysql_fetch_array($this->result);
	}

	/*
	 * Fetch-Assoc-Methode
	 * -------------------
	 * Rückgabewert: Ein Array das der Ergebniszeile entspricht oder FALSE,
	 * wenn keine weiteren Zeilen verfügbar sind. 
	 */
	public function fetch_row()
	{
		return mysql_fetch_row($this->result);
	}

	/*
	 * Destruktormethode
	 * -----------------
	 * Bricht die Verbidung ab, wenn die Klase MySQL keine Verwendung mehr hat.
	 */
	public function __destruct()
	{
		mysql_close($this->connection);
	}

}

?>

Testdatei
PHP:
<?php

include('mysql.class.php');

try
{
	$MySQL = new MySQL();
	$MySQL->prepare("SELECT * FROM user WHERE name='%s' AND password='%s'");
	$MySQL->execute("name, password");
	while($row = $MySQL->fetch_assoc())	print_r($row);
	//$MySQL->prepare("INSERT INTO user (name, password, email, time) VALUES ('%s', '%s', '%s', '%d')");
	//$MySQL->execute("test, test2, t@t.de, ".time()."");
	$MySQL->prepare("SELECT * FROM user");
	$MySQL->execute();
	while($row = $MySQL->fetch_assoc())	print_r($row);
}
catch(Exception $e)
{
	$arrError = array(
		'message'	=> $e->getMessage(),
		'file'		        => $e->getFile(),
		'line'		=> $e->getLine()
	); 
}

if(isset($arrError)) var_dump($arrError);

?>

Ich habe mich auch etwas an dem folgenden Artikel gestützt - so bin ich auf die sprintf Funktion gestoßen. Nun frage ich mich halt, ob die denn auch ausreichend ist? Oder ob man die Klasse noch weiter ergänzen, verbessern oder sogar komplett neu konzipieren sollte? Vielen Dank schonmal!
Gruß, walle
 
Eine Frage nach der Grundkonzeption...
Du benutzt PHP5 OOP Features, also benutzt du PHP5. Warum setzt du dann noch auf die mysql_* Funktionen und nicht auf MySQLi?

Noch dazu würde ich niemals das "@" benutzen in einer Klasse. Benutze lieber [phpf]error_reporting[/phpf] um alle Fehler auszublenden. Oder noch besser:
[phpf]ini_set[/phpf] auf display_errors

Ansonsten würde mir diese Klasse keinen Mehrwert bei der Benutzung bringen.

  • keine Prepared Statements (dadurch auch gegen SQL Injektionen geschützt)
  • Ich muss meine Schleifen immer noch selber durchlaufen, ein fertiges Array wäre doch schöner?
  • mit MySQLi nutzt du den neuen mysqlnd und hast dadurch Geschwindigkeitsvorteile im Vergleich zu den alten mysql_* Funktionen
  • Es fehlt eine Zählfunktion für die Ergebnisse die man bekommt
  • Die Funktion execute() ist ohne Rückgabewert. Woher weiß mein Skript ob das Query erfolgreich war oder nicht?
  • Ich würde auf die Benutzung von Konstanten die außerhalb der Klasse benutzt werden verzichten und lieber mit Übergabewerten arbeiten.

Sorry, wenn es etwas ruppig rüberkommt, aber ich wollte den Post noch beenden und jetzt muss ich los.
 
Wenn du schon MySQLi nutzt, dann brauchst du dir auch keine eigene Klasse mehr schreiben, denn MySQLi beinhaltet alles, was du versucht hast umzusetzen und das um einiges besser und vollständiger. Ich persönlich habe auch mal eine MySQL-Klasse geschrieben bis ich auf MySQLi gestoßen bin und danach die Idee verwarf.
 
Eine eigene Wrapper Klasse macht in diesem Fall keinen Sinn, da stimme ich zu.
Sinnvoll wäre eventuell eine Erweiterung der MySQLi Klasse die auf deine Ansprüche geeicht ist.
 
Ok, habe mich eben mit dem Artikel auf php.net auseinandergesetzt - joa, ich brauche da nicht wirklich etwas Eigenes zu machen. Ist ja soweit alles "fertig". Danke trotzdem :)
 
Zurück