2erlei/fl/data/access/mysql.php

349 lines
8.2 KiB
PHP
Raw Normal View History

2019-09-22 14:53:30 +00:00
<?php
/**
* Speicherung in einer MySQL-Datenbank
*
* Der Zugriff auf die Datenbank erfolgt über CRUD ZugriffsFunktionen
* - create
* - retrieve
* - update
* - del
* - query
*
* Weiterhin gibt es:
* - clear_table
* - optimize_table
*
* @version 0.2.1
*/
class fl_data_access_mysql extends fl_data_access_database implements data_access {
protected $connection;
public $database;
public $table_prefix = '';
public $true_value = 1;
public $false_value = 0;
public function __construct($config) {
$this->table_prefix = (string) $config['table_prefix'];
$this->_open_db($config['host'], $config['database'], $config['user'], $config['pass']);
}
/**
* Datenbankeintrag erzeugen
*
* Die create-Methode bietet eine Schnittstelle, um Daten zur Datenbank
* hinzuzufügen.
*
* @param string $table Tabellenname
* @param array $data assoziatives Array, das die Daten enthält.
* @param string $type Art der Einfügeoperation (INSERT, INSERT IGNORE, REPLACE)
* @return string Ergebnis der Datenbankoperation
*/
public function create($table, array $data, $type='INSERT') {
$data_length = count($data);
$i = 0;
switch ( strtoupper($type) ) {
case 'IGNORE':
case 'INSERT IGNORE':
$type = 'INSERT IGNORE';
break;
case 'REPLACE':
case 'INSERT':
$type = strtoupper($type);
break;
default:
$type = 'INSERT';
break;
}
$sql = $type . " INTO ".$this->get_table_name($table)." SET ";
foreach ($data as $field=>$content) {
$this->_secureFieldContent($content);
$sql .= " ".$field."='".$content."'";
if ( ( $data_length - 1 ) > $i++ )
$sql .= ",";
}
$result = $this->query($sql);
return $result;
}
/**
* Datenbankeintrag holen
*
* Die retrieve-Methode bietet eine Schnittstelle, um Daten aus der
* Datenbank zu lesen.
*
* @param string $table Tabellenname
* @param string $field Feldnamen, die abgefragt werden
* @param string $condition Bedigungen, nach denen die Tabellenzeilen ausgewählt werden
* @param string $order Sortierungsreihenfolge
* @param string $limit maximale Anzahl von Zeilen
* @return array Assoziatives Array mit den Daten.
*/
public function retrieve($table, $field='*', $condition='', $order='', $limit='') {
if ( $limit == '') {
$sql_limit = FALSE;
} elseif ( strpos($limit, ',') === FALSE ) {
$sql_limit = '0,' . $limit;
} else {
$sql_limit = $limit;
}
$sql = "SELECT ".$field." FROM ".$this->get_table_name($table);
if ( !empty($condition) )
$sql .= " WHERE ".$condition;
if ( !empty($order) )
$sql .= " ORDER BY ".$order;
if ( $sql_limit !== FALSE )
$sql .= " LIMIT ".$sql_limit;
$result = $this->query($sql);
return $result;
}
/**
* Datenbankeintrag aktualisieren
*
* Die update-Methode bietet eine Schnittstelle, um Daten in der Datenbank
* zu aktualisieren. Dies ist die vermutlich die häufigste Form der
* Speicherung.
*
* @param string $table Tabellenname
* @param array $data assoziatives Array, das die Daten enthält.
* @param int $id id des Datenbankeintrages
* @param string $id_field Feldname des id-Feldes
* @param boolean $all Alle Zeilen verändern
*
* @return string Ergebnis der Datenbankoperation
*/
public function update($table, array $data, $id, $id_field='id', $all=FALSE) {
$data_length = count($data);
$i = 0;
$sql = "UPDATE ".$this->get_table_name($table)." SET".PHP_EOL;
foreach ($data as $field=>$content) {
$this->_secureFieldContent($content);
$sql .= " ".$field."='".$content."'";
if ( ($data_length - 1 ) > $i++ )
$sql .= ",";
}
if ( !$all ) {
$sql .= " WHERE ".$id_field."='".$id."'";
}
$result = $this->query($sql);
return $result;
}
/**
* Datenbankeintrag löschen
*
* Die del-Methode bietet eine Schnittstelle, um Daten aus der Datenbank
* zu löschen.
*
* @param string $table Tabellenname
* @param int $id id des Datenbankeintrages
* @return boolean Ergebnis der Datenbankoperation
*/
public function del($table, $id) {
if ( !is_numeric($id) ) {
return FALSE;
}
$sql = "DELETE FROM ".$this->get_table_name($table)."
WHERE id='".$id."' LIMIT 1";
$result = $this->query($sql);
return $result;
}
/**
* Datenbank-Ergebnisse in richtige Typen umwandeln
*
* @param string table
* @param array $result
* @return array
* @todo Funktion fuer MySQL umarbeiten
*/
public function convert_result($table, $result) {
return $result;
$table = $this->get_table_name($table);
$converted = $result;
$sql = <<<SQL
SELECT column_name AS col, CASE
WHEN data_type = 'numeric' THEN 'float'
ELSE data_type
END AS type
FROM information_schema.columns
WHERE table_name='{$table}'
AND data_type IN ('boolean', 'integer', 'numeric');
SQL;
$types = $this->query($sql);
foreach ( $result as $row_num => $rows ) {
foreach ( $types as $type ) {
$col = $type['col'];
$new_type = $type['type'];
$converted[$row_num][$col] = settype($row[$col], $new_type);
}
}
return $converted;
}
/**
* Tabelle leeren
*
* @param string $table Tabellennname
* @return boolean
*/
public function clear_table($table) {
$sql = 'TRUNCATE TABLE '.$this->get_table_name($table);
$result = (boolean) $this->query($sql);
return $result;
}
/**
* Tabelle optimieren
*
* @param string $table Tabellenname
* @return boolean
*/
public function optimize_table($table) {
$sql = 'OPTIMIZE TABLE ' . $this->get_table_name($table);
$result = (boolean) $this->query($sql);
return $result;
}
/**
* Datenbankabfrage als SQL abgeben
*
* @param string $sql
* @return mixed
*/
public function query($sql) {
return $this->_query_db($sql);
}
/**
* Zuletzt eingefügte ID zurückgeben
*
* @param string $table
* @return integer
*/
public function last_insert_id($table) {
return mysql_insert_id($this->connection);
}
/**
* Eindeutigen Bezeichner für eine Tabelle zurückgeben
*
* @param string $table
* @return string
*/
public function get_table_name($table) {
return $this->table_prefix . $table;
}
// interne Funktionen
/**
* Datenbankverbindung öffnen
*
* @param string $host
* @param string $db
* @param string $user
* @param string $pass
*/
private function _open_db($host, $db, $user, $pass) {
if ( !extension_loaded('mysql') ) {
die("PHP-Erweiterung 'mysql' nicht geladen");
}
$this->connection = @mysql_connect( $host, $user, $pass)
OR die("Keine Verbindung zur Datenbank m&ouml;glich. Fehlermeldung: ".mysql_error($this->connection));
$this->database = $db;
mysql_query('SET NAMES "utf8"', $this->connection);
$this->_select_db();
}
/**
* Datenbank auswählen
*/
private function _select_db() {
mysql_select_db($this->database)
OR die("Konnte Datenbank nicht benutzen, Fehlermeldung: ".mysql_error());
}
/**
* Datenbank abfragen
*
* @param mixed $sql String oder Array, das die SQL-Abfragen enthält
* @todo Funktion überarbeiten
* @return mixed
*/
private function _query_db($sql) {
$this->_select_db();
if ( is_array($sql) ) {
foreach ( $sql as $nr => $query ) {
$output[$nr] = $this->query( $query );
}
} else {
$this->log_query($sql);
$output = array();
$aktionen = array('UPDATE','DELETE', 'ALTER ', 'CREATE', 'DROP T', 'TRUNCA', 'REPLAC', 'OPTIMI');
$abfrage = is_string($sql) ? trim($sql) : $this->error('Fehlerhafte Daten', $sql);
$result = mysql_query($abfrage, $this->connection) OR $this->error(mysql_error($this->connection), $sql);
$abfragetyp = strtoupper(substr($abfrage,0,6));
if ( ( in_array($abfragetyp,$aktionen) ) ) {
$output = ( $result )? TRUE: FALSE;
} elseif ( ($abfragetyp == 'INSERT') ) {
$output = ( $result )? $this->last_insert_id(): FALSE;
} else {
while($row = mysql_fetch_assoc($result)) {
$output[] = $row;
}
}
unset($abfragetyp);
unset($aktionen);
}
return $output;
}
/**
* Feldinhalte gegen Hackingversuche schützen
*
* Dies sind nur grundlegende Schutzmaßnahmen
*
* @param mixed &$var
*/
private function _secureFieldContent(&$var){
if ( is_array($var) ) {
$varvalue = var_export($var, TRUE);
$this->error('Array sollte gespeichert werden.', $varvalue );
}
$var = mysql_real_escape_string($var, $this->connection);
}
}
?>