j4nk3y: PHP Oop Datenbank Klasse

Beitrag lesen

Guten Morgen zusammen,

Ich hatte gestern schonmal ein wenig Zeit mich an einen ersten Entwurf zu setzen.

Mir ist bewusst, dass es sicher noch Verbesserungspotenzial gibt aber seht selbst. Für Verbessunrgsvorschläge bin ich gerne offen.

class DB {
	
	private function __construct($user, $password, $database, $host = 'localhost') {
		self::$user = $user;
		self::$password = $password;
		self::$database = $database;
		self::$host = $host;
	}
	
	private function __clone() {}
	
	public static function getInstance(  ) {
		if ( !self::$instance ) { 
			self::$instance = new PDO("mysql:dbname=$this->$database;host=$this->$host", $this->$user, $this->$password);
			self::$instance -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
			self::$instance -> beginTransaction();
		}
		
		return self::$instance;
	}
	
	public function select ( $table, $columns, $where, $limit ) {
		
		$stmt = self::$instance -> prepare( $this->prepareQuery ( 'select', $table, $columns, $where, $limit ) );
		
		if ( is_array( $where[0] ) ) {
			$result = [];
			foreach ( $where as $value ) {
				$stmt -> bindValues ( $value );
				if ( !$stmt -> execute() ) {
					return false;
				}
				$result[] =  $stmt -> fetchAll();
			}
			return $result
		} else {
			$stmt -> bindValues ( $where );
			if ( !$stmt -> execute() ) {
				return false;
			}
			return $stmt -> fetchAll();
		}
	}
	
	public function insert ( $table, $data ) {
		$stmt  = self::$instance -> prepare( $this->prepareQuery ( 'insert', $table, $data  ) );
		
		if ( is_array( $data[0] ) ) {
			foreach ( $data as $value ) {
				$stmt -> bindValues ( $value );
				if ( !$stmt -> execute() ) {
					return false;
				}
			}
			return $result
		} else {
			$stmt -> bindValues ( $data );
			if ( !$stmt -> execute() ) {
				return false;
			}
		}
		return true;
	}
	
	private function getLastInsertId () {
        return self::$instance->lastInsertId();
    }
	
	public function update ( $table, $data, $where ) {
		$stmt  = self::$instance -> prepare( $this->prepareQuery ( 'update', $table, $data, $where ) );
		
		if ( is_array( $data[0] ) ) {
			foreach ( $data as $key => $value ) {
				$i = 0;
				foreach ( $value as $val ) {
					$toBind[$i] = $val;
					++$i;
				}
				foreach ( $where as $val ) {
					$toBind[$i] = $val;
					++$i;
				}
				
				$stmt -> bindValues ( $toBind );
				
				if ( !$stmt -> execute() ) {
					return false;
				}
			}
			return $result
		} else {
			$stmt -> bindValues ( $data );
			if ( !$stmt -> execute() ) {
				return false;
			}
		}
		return true;
	}
	
	public function delete ( $table, $where ) {
		$stmt = self::$instance -> query( $this->prepareQuery ( 'delete', $table, $where ) );
		
		if ( !$stmt -> execute() ) {
			
		}
	}
	
	public function commit () {
		self::$instance -> commit();
	}
	
	private function rollBack () {
		self::$instance -> rollBack();
	}
	
	private function prepareQuery ( $type, $table, $data, $where = null, $limit = null ) {
		
		$query = '';
		$columns = '';
		$placeholders = '';
		$values = [];
		
		if ( !is_null($data) && $type === 'select' ) {
			$data = ['*'];
		}
		
		if ( $data ) {
			foreach ( $data as $column => $value ) {
				
				if ( $type === 'Select' ) {
					$columns .= "{$value},";
				} elseif ( $type === 'insert' ) {
					$columns .= "{$column},";
					$placeholders .= '?,';
				} elseif ( $type === 'update' ) {
					$columns .= "{$column}=?,";
				}
				
				$values[] = $value;
			}
			
			substr($columns, 0, -1);
			substr($placeholders, 0, -1);
			
			if ( $type === 'Select' ) {
				$query = "SELECT {$columns} FROM {$table}";
			} elseif ( $type === 'insert' ) {
				$query = "INSERT INTO {$table} ({$columns}) VALUES ({$placeholders})";
			} elseif ( $type === 'update' ) {
				$query = "UPDATE {$table} SET {$columns}";
				
			} elseif ( $type === 'delete' ) {
				$query = "DELETE FROM {$table}";
			}
			
		} else {
			return false;
		}
		
		if ( $where ) {
			
			$query .= " WHERE ";
			foreach ( $where as $column => $value) {
				$clause .= "{$column} =? AND ";
			}
			
			substr($clause, 0, -5);
			$query .= $clause;
		}
		
		if ( $limit ) {
			$query .= " LIMIT = {$limit}";
		}
		
		return $query;
	}
	
	private function bindValues ( $data ) {
		$i = 1;
        foreach ( $data as $value ) {
            $varType = is_null( $value ) ? \PDO::PARAM_NULL : is_bool( $value ) ? \PDO::PARAM_BOOL : is_int( $value ) ? \PDO::PARAM_INT : \PDO::PARAM_STR;
			
            if ( !self::$instance->bindValue ( ++$i, $value, $varType ) ) {
			   return false;
			}
        }
        return true;
    }
	
	
	public function commit (  ) {
		if ( !self::$instance -> commit() ) {
		   return false;
		   
		}
		return true;
	}
	
	private function rollBack (  ) {
		if ( !self::$instance -> rollBack() ) {
		   return false;
		   
		}
		return true;
	}
	
}

Ziel ist es für mich, die Querys in der folgenden Form zu übergeben:

select ( "tablename",
				["colA","colB"] || null,
				["colA" => 1, "colB" => 2] || [["colA" => 1, "colB" => 2], ["colA" => 2, "colB" => 3]],
				10 || null );
insert ( "tablename",
				["colA" => 1, "colB" => 2] || [["colA" => 1, "colB" => 2], ["colA" => 2, "colB" => 3]],
				["colA" => 2, "colB" => 3] );
update ( "tablename",
				["colA" => 1, "colB" => 2] || [["colA" => 1, "colB" => 2], ["colA" => 2, "colB" => 3]],
				["colA" => 2, "colB" => 3] );
delete ( "tablename",
				["colA" => 2, "colB" => 3] );

Dann noch einmal kurz auf die Sicherheit. Escapen bzw die übergebenen Daten behandeln damit eine Injection nicht möglich ist, brauchte ich bei PDO nicht mehr, richtig?

Und noch ein kleiner Punkt, wie ist das, wenn ich noch keine Datenbank erstellt habe? Reicht es dann mysql:dbname=$this->$database;host=$this->$host zu mysql:dbname=$this->$database zu ändern? Und wie verbinde ich mich dann zu der Datenbank wenn ich diese durch einen CREATE DATABASE-Query erstellt habe?

Vielen Dank und noch ein schönes Wochenende.

Gruß
Jo