Rachus: MySQL Loginsystem

Beitrag lesen

Hallöchen,

Aber, wie gesagt: YAGNI - lass es weg, bis du echten Bedarf hast.

gut, ich lass den Mehrverbindungssupport weg!

Anhand deinen Tipps habe ich un mal meine Klasse modifiziert. Da ich nicht wusste, wie ich aus Arrays mehrere Funktionsparameter für sprintf() mache, habe ich das ganze etwas anders realisiert.
Ein query()-Aufruf kann nun so aussehen:
DBConnection::query("SELECT foo FROM bar WHERE bar.foo=?0 AND bar.x=?1", array($_POST['id'], $_POST['name']), array(DBConnection::NUMBER, DBConnection::LITERAL));
Hoffentlich ist es verständlich. Da mir mein Editor allerdings "INTEGER", "STRING" und "FLOAT" als bekannt angab, wollte ich diese Bezeichner nicht für die Klassenkonstanten verwenden.

Auch weiß ich nicht, wie ich bei Exceptions irgendwo den Fehler "hinlogge". Daher ist auch das nicht darin. Sonst würde ich diese Klasse jetzt schon recht angenehm finden. Eventuell noch etwas funktional modelieren, aber sonst habe ich mal das Gefühl, dass das so OK ist.

<?php  
class DBConnection  
{  
	static private $db;  
	static private $settings;  
	  
	const NOESCAPE=0;  
	const NUMBER=1;  
	const DECIMAL=2;  
	const LITERAL=3;  
	const IDENTIFIER=4;  
	  
	static public function Init($host, $username, $passwd, $dbname, $port=3306)  
	{  
		self::$settings=array($host, $username, $passwd, $dbname, $port);  
	}  
	  
	static public function query($sql, $values, $types, $resultmode=MYSQLI_STORE_RESULT)  
	{  
		if (!isset(self::$settings)) throw new Exception('not initialized', 1);  
		if (!isset(self::$db))  
		{  
			if (!self::connect()) throw new Exception('could not connect', 2);  
		}  
		  
		for ($i=count($values); $i>=0; --$i)  
		{  
			if ($types[$i]==self::NUMBER)  
			{  
				$sql=str_replace('?'.$i, intval($values[$i]), $sql);  
			}  
			else if ($types[$i]==self::DECIMAL)  
			{  
				$sql=str_replace('?'.$i, floatval($values[$i]), $sql);  
			}  
			else if ($types[$i]==self::LITERAL)  
			{  
				$sql=str_replace('?'.$i, self::quote_expression($values[$i]), $sql);  
			}  
			else if ($types[$i]==self::IDENTIFIER)  
			{  
				$sql=str_replace('?'.$i, self::quote_identifier($values[$i]), $sql);  
			}  
			else  
			{  
				$sql=str_replace('?'.$i, $values[$i], $sql);  
			}  
		}  
		$sql=str_replace('??', '?', $sql);  
		  
		return self::$db->query($sql, $resultmode);  
	}  
	  
	static public function quote_identifier($value)  
	{  
		return '`'.str_replace('`', '``', &$value).'`';  
	}  
	  
	static public function quote_expression($value)  
	{  
		return '\''.self::$db->real_escape_string(&$value).'\'';  
	}  
	  
	static private function connect()  
	{  
		self::$db=new MySQLi(self::$settings[0], self::$settings[1], self::$settings[2], self::$settings[3], self::$settings[4]);  
		if (self::$db->connect_error) return false;  
		else return true;  
	}  
}  
?>

Wahrscheinlich könnte man die Einstellungen auch anders handhaben, aber das wirst du mir sicher wieder mitteilen.

Da fehlt vermutlich noch die Join-Bedingung (in WHERE: x.y_id = y.id - oder sowas in der Art).

In Ordnung, an sowas habe ich bei meinem Beispiel nicht gedacht...

Für String/Zahl/null kann man den Typ des Arguments auswerten und weiß dann, ob gequotet werden muss (String) oder nicht darf (null) (oder ob es egal ist (int/float)). Beim Identifier hat man ein Problem, den muss man irgendwie gänzlich separat behandeln - da fällt mir grad keine clevere Lösung ein.

Dafür habe ich jetzt ja eine Lösung ganz ohne sprintf() gefunden (Gründe siehe oben). Hat lange Überlegungszeit gekostet, aber ichbin jetzt einigermaßen zufrieden.

Die Factory kann sich vor der Rückgabe an den Verwender die erzeugte Instanz merken und so die selbe Instanz auch noch an andere Verwender rausgeben. Beim direkten Instantiieren bist du der alleinige Besitzer der Instanz und jeder new-Aufruf erstellt zwingend eine neue.

Dadurch, dass ich jetzt aber das ganze für nur eine Verbindung erledige, erübrigt sich die Factory.

Übrigens, falls du dich fragst, warum ich nicht vorschlage, DB von mysqli abzuleiten [...]

Hatte ich nicht vor. Auf so eine Idee wäre ich, um ehrlich zu sein, auch nicht gekommen.

Einen schönen Abend

Rachus