Hallo dedlfix.
Also, ich beschränke die Query erledigende Funktion mal auf das Nötigste.
Danke.
Das heißt, sie bekommt ein fertiges Statement ohne dass noch Parameter eingebaut werden können/müssen. Ebenfalls nicht mit berücksichtigt ist das Ermitteln und Zurückgeben von Result-Metadaten wie last_insert_id oder affected_rows.
Ich denke das werde ich im Nachhinein noch selber auf die Reihe bekommen.
$mysqli = $this->_getConnection(); // das ist eine private Methode, die mit ein mysqli-Objekt mit aktiver Verbindung gibt.
_getConnection(), was ist das? meine getInstance()?
Bzw. in meiner db-Klasse wird die Mysql-Verbindung ja in private static $_db_connection abgelegt und da die Methode query() ja in dieser Klasse liegt, einfach $mysqli = self::$_db_connection?
Meine db-Klasse baut ja beim instanzieren automatisch eine MySQLi-Verbindung auf, sie wird _immer_gebraucht bei jeder Methode in der Klasse.
»» Ne weitere Frage:
»»
»» Wenn ich eine Klasse habe und meine Datenbank-Klasse(db) nutzen möchte, dann hole ich mir eine Instanz so:
»»
»» ~~~php
class beispiel{
»» private static $dbcon;
»»
»» public function __construct(){
»» self::$dbcon=db::getInstance();
»» }
»» }
>
> Ich würde die Instanz nicht auf Vorrat holen sondern jeweils in den jeweiligen Methoden, in denen sie benötigt wird und in einer lokalen Variable ablegen.
Okay habe ich geändert. Jede Methode die eine Verbindung braucht, holt sich per getInstance() eine Instanz und speichert sie lokal(innerhalb der Methode meinst du oder?) ab.
> »» Allerdings ginge doch auch direkt:
> »» b)
> »» ~~~php
public workWith(){
> »» db::db_query($sql);
> »» }
»»
»» Da db_query eine statische Methode ist.Für die statische Methode wird ja auch keine Instanz benötigt. du brauchst sie dann nicht abzufragen. Die Frage ist, ob überhaupt eine Instanz benötigt wird oder ob die public-Methoden alle atomar sind und damit statisch sein können. Dann brauchst du nämlich auch kein öffentliches Singleton, um die Instanz zu holen.
Argh - jetzt bin ich wieder völlig überfordert und weiß nicht mal ob ich mich in einer YAGNI-Welt befinde, denn die ganze Zeit sitze ich daran eine db-Klasse auf Singleton-Pattern aufzubauen und nun sind alle Methoden static und ich kann jederzeit auf sie zugreifen auch ohne die Instanz.
Irgendwie bin ich stark verwirrt und weiß garnicht mehr wofür ich das Singleton da am besten nutze und warum ich nicht einfach alles static mache wie meine tools-Klasse. -______-
Ich poste mal meine Aktuelle db-Klasse um sie Deiner/Eurer Bewertung unterziehen zu lassen:
class db{
# Instanz - Singleton Pattern
private static $_instance;
# Verbindungsdaten
private static $_db_host;
private static $_db_user;
private static $_db_pw;
private static $_db_name;
private static $_db_connection;
private static $_count_array;
private static $_rwu_sentence;
public static $query;
public static $result;
# Konstruktor - private - kann nicht aufgerufen werden
private function __construct(){
self::db_connect();
}
# Singleton Pattern
public static function getInstance()
{
if (!isset(self::$_instance)) {
self::$_instance = new db();
} else {
die("Es ist bereits eine Instanz vorhanden - schliessen Sie diese um eine weitere zu erstellen.<br/>
Singleton-Pattern-Error.");
}
return self::$_instance;
}
# Datenbankwerte setzen
public static function db_set_vars($host,$name,$pw,$dbname){
self::$_db_host=$host;
self::$_db_user=$name;
self::$_db_pw=$pw;
self::$_db_name=$dbname;
}
# Zur Datenbank verbinden
private static function db_connect()
{
self::$_db_connection = new mysqli(self::$_db_host, self::$_db_user, self::$_db_pw, self::$_db_name);
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
} else {
return true;
}
}
######################################################################################################
################# db_make_rwu_sentence
######################################################################################################
// Ein-/Auslesewerte aneinanderreihen
/*
3 Typen:
Typ 1: foo,bar
Typ 2: 'foo','bar'
Typ 3: foo='bar',foo='bar',
Typ 4: ?,?,? - MySQLi Platzhalter für prepared Statements
*/
public static function db_make_rwu_sentence($what_rwu,$what_insert,$rwu){
$x=0; // Zähler auf NULL(0) setzen
self::$_rwu_sentence=''; // Zurücksetzen des Ausdrucks
foreach($what_rwu as $what){
if($rwu==1||$rwu==2){ // Typ 1 oder 2
self::$_rwu_sentence .= ($rwu==1) ? $what : "'".$what."'";
} elseif($rwu==3) { // Typ 3
self::$_rwu_sentence .= $what."='".mysqli_real_escape_string($what_insert[$x])."'";
} elseif($rwu==4) { // Typ 4
self::$_rwu_sentence .= "?";
}
self::$_rwu_sentence .= ($x < self::$_count_array - 1) ? "," : "";
++$x; // hochzählen
}
return self::$_rwu_sentence;
}
######################################################################################################
################# db_create_normal_query
######################################################################################################
// Erstellt einen Query
/*
$what_array -> Spaltennamen
$what_insert -> Was reingeschrieben wird
$from_table -> welche Tabelle angesprochen wird
$when -> BEDINGUNG! Wann macht der Querie etwas? Wo? -> $WHEN....
$whatkind -> Was für ein RUDI Query ist es? (SELECT(3), UPDATE(2), DELETE(4), INSERT(1))
*/
public static function db_create_normal_query($what_array,$what_insert, $from_table, $when, $whatkind){
// RUDI-Queries
# Wieviele Werte sind ein-/auszulesen
self::$_count_array=count($what_array);
if ($whatkind==1) { // SELECT ((R)ead)
self::$query="SELECT ".self::db_make_rwu_sentence($what_array,'',1)." FROM ".$from_table." WHERE ".$when;
} elseif ($whatkind==2) { // UPDATE ((U)pdate)
tools::check_array_numbers($what_array,$what_insert);
self::$query="UPDATE ".$from_table." SET ";
self::$query.=self::db_make_rwu_sentence($what_array,$what_insert,3);
self::$query.=" WHERE ".$when;
} elseif ($whatkind==3) { // DELETE ((D)elete)
self::$query="DELETE FROM ".$from_table." WHERE ".$when;
} elseif ($whatkind==4) { // INSERT ((I)nsert)
if(!tools::check_array_numbers($what_array,$what_insert)) self::db_errors("Die Arrays sind nicht gleichlang!");
self::$query="INSERT INTO ".$from_table." (".self::db_make_rwu_sentence($what_array,'',1);
self::$query.=") VALUES (".self::db_make_rwu_sentence($what_insert,'',2).")";
} else { // Kein Typ -> Error
self::db_errors("Es wurde kein Typ ausgewählt");
}
self::db_query(self::$query);
}
/**
* Query abarbeiten
*
* @param string $sql ein SQL-Statement
* @param mixed $asObject false: Fetchen als Array
* true: Fetchen als Objekt
* string: Name der zu instantiierenden Klasse
* @param array $objectParams optionale Parameter @see mysqli_result::fetch_object()
* @return array Ergebnismenge als Array mit Arrays oder Objekten
*/
# Query ausführen
public static function db_query($sql, $asObject = false, $objectParams = null) {
$result = array();
$mysqli = self::$_db_connection; // Ich hoffe das ist so richtig
# $mysqli = $this->_getConnection(); // das ist eine private Methode, die mit ein mysqli-Objekt mit aktiver Verbindung gibt.
$mysqliResult = $mysqli->query($sql, MYSQLI_USE_RESULT);
if (!$mysqliResult)
throw new Exception(...);
if ($mysqliResult instanceof mysqli_result) {
try {
if ($asObject) { // true oder string
if (is_string($asObject)) {
if (!class_exists($asObject))
throw new Exception('class ' . $asObject . ' does not exist.');
} else { // kein Klassenname übergeben, Standard-Klasse verwenden lassen
$asObject = null;
$objectParams = null;
}
while ($row = $mysqliResult->fetch_object($asObject, $objectParams))
$result[] = $row;
} else
while ($row = $mysqliResult->fetch_assoc())
$result[] = $row;
} finally {
// wird unbedingt benötigt, wegen MYSQLI_USE_RESULT @see mysqli::query()
$mysqliResult->free();
}
}
return $result;
}
/*
# Clone - unterbinden
public function __clone(){
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
}
Mir ist klar das dort noch eine Fehlerbehandlung passieren muss, ich werde dafür eine Log-Klasse schreiben die MySQL-Fehler loggt usw..
Weitere Fragen in meinem Kopf sind ausserdem immernoch:
1. Sollte der "Connect" im Konstruktor stattfinden oder nicht?
2. Wie könnte der Destruktor aussehen?
Lg, danke für deine Mühe,
Chris