Scripts

Query Generator Class

Ik heb een class gemaakt om samen te werken met PDO (of eender welke database) die mooie query's maakt. Voorlopig is hij geoptimaliseerd voor mySQL, maar met wat kleine aanpassingen is hij ook te gebruiken voor PostgreSQL. Voorlopig doet hij nog maar basis dingen bij de select (COUNT en AS bv. kan hij nog niet), maar later komt er ook input controle. Nu kan je misschien denken, "Dat is toch meer (typ)werk om een query te maken zo?". Dat is enerzijds wel zo, maar nu heb je wel het voordeel dat niet je hele query als string gekleurd staat maar in verschillende php kleuren. PS: De and_condition(); en or_condition(); werken precies hetzelfde als de where();

query-generator-class
voorbeeldcode.php
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
include('class.query.php');
define('EOL', "\n");

/* Examle query's */

// vb1: insert met opgave van de velden en de waarden zijn telkens een array
$query[] = Query::insert('users',array('username','password','email'))
			->values( array('Hipska','test','email'), array('Steffan','naffetS','mail2') );

// vb2: insert zonder opgave van de velden en de waarden zitten in 1 grote array
$query[] = Query::insert('users') // geef je geen velden op, dan moet in de waarden alle velden van de tabel zitten
			->values( array( array('Hipska','test','email') , array('Steffan','naffetS','mail2') ) );

// vb3: select meerdere tabellen door join en een limit
$query[] = Query::select( array('id','page','time'), array('username','email') )->from('log')
			->join('users','userid','id')->limit(30,10);

// vb4: select met union en een order by
$query[] = Query::select('id','title','time')->from('posts')->order(array('time' => 'DESC'))
			->union('all')->from('comments')->order(array('time' => 'ASC'));

// vb5: select met where statement
$query[] = Query::select(array('id','username'))->from('users')
            ->where(array('permission' => 'mod','admin','smod'), 'OR');

// vb6: update met where volgens 1e methode
$query[] = Query::update('users')->set(array('permission' => 'admin'))
			->where(array('id' => 2, 'permission' => 'mod'));

// vb7: delete met where volgens de 2de methode
$query[] = Query::delete('users')->where('id > 2');

// vb8: volledige tabel legen ( kan ook met from() )
$query[] = Query::delete('log');

// vb9: tabel verwijderen
$query[] = Query::drop('users');

/* Results of the class */
echo '<pre>' . EOL;
foreach ($query as $sql) echo $sql . EOL;	
highlight_file(__FILE__);
highlight_file('class.query.php');
echo '</pre>';

?>
Results:
[code]INSERT INTO users (username, password, email) VALUES ( 'Hipska', 'test', 'email' ), ( 'Steffan', 'naffetS', 'mail2' )
INSERT INTO users VALUES ( 'Hipska', 'test', 'email' ), ( 'Steffan', 'naffetS', 'mail2' )
SELECT log.id, log.page, log.time, users.username, users.email FROM log JOIN users ON ( log.userid = users.id ) LIMIT 30, 10
SELECT id, title, time FROM posts ORDER BY time DESC UNION ALL SELECT id, title, time FROM comments ORDER BY time ASC 
SELECT id, username FROM users WHERE (permission = 'mod' OR permission = 'admin' OR permission = 'smod') 
UPDATE users SET permission = 'admin' WHERE (id = '2' AND permission = 'mod') 
DELETE FROM users WHERE id > 2 
DELETE FROM log 
DROP TABLE users[/code]
class.query.php
<?php

/**
 * class Query
 *
 * Maak snel en overzichtelijk een query
 *
 * @author Hipska
 * @link http://www.hipska.be.tc
 */

class Query {
	
	private $query = '';
	private $tables = array();
	private $fields = array();
	
	
	/**
	 * Query::__construct()
	 *
	 * Constructor: Maak een nieuwe Query instantie.
	 *
	 * @param string $sql: string om de query mee te beginnen
	 * @author Hipska
	 */
	public function __construct( $sql = '' ){
		$this->query = $sql;
	}
	
	/**
	 * Query::__toString()
	 *
	 * geef de de query weer.
	 *
	 * @return string: de volledige query
	 */
	public function __toString() {
		return $this->query;
	}
	
	/**
	 * Query::select()
	 *
	 * Maak een SELECT query.
	 * Als parameter vul je niets in om alle velden te selecteren.
	 * Wil je meerdere velden selecteren, dan kan je een array met de velden opgeven 
	 * of de velden als aparte parameter invullen.
	 * Wil je velden van verschillende tabellen selecteren, 
	 * dan geef je per tabel een arry met de velden.
	 *
	 * @param mixed $fields: veld(en) om te selecteren uit de tabel(len)
	 * @access public
	 * @author Hipska
	 */
	public function select( $fields = '*' ) {
		if(is_array($fields) and func_num_args() > 1){
			$fields = array(); $tables = 0;
			foreach (func_get_args() as $field) {
				$table = 't'.++$tables.'.';
				$fields[] = $table . implode(', '.$table, $field);
			}
		}elseif(!is_array($fields)){
			$fields = func_get_args();
		}
		
		$query = new self('SELECT ' . implode( ', ', $fields ) . ' ');
		$query->fields = $fields;
		return $query;
	}
	
	/**
	 * Query::update()
	 *
	 * Maak een UPDATE query.
	 *
	 * @param string $table: de tabel welke je wil updaten
	 * @access public
	 * @author Hipska
	 */
	public function update( $table ){
		return new self('UPDATE ' . $table . ' ' );
	}
	
	/**
	 * Query::delete()
	 *
	 * Maak een DELETE query.
	 * Laat $table leeg om alle rijen van een tabel te wissen.
	 * ( Query::from() is dan wel nog nodig om de tabel te kiezen )
	 *
	 * @param string $table: tabel waar er rijen uit verwijdert moeten worden
	 * @access public
	 * @author Hipska
	 */
	public function delete( $table = null ){
		return new self('DELETE' . (is_null($table)? ' ' : ' FROM ' . $table . ' ') );
	}
	
	/**
	 * Query::insert()
	 *
	 * Maak een INSERT query.
	 * kies in welke tabel en welke velden er in 
	 * de rijen staan die ingevoegd moeten worden
	 *
	 * @param string $table: tabel waar er rijen ingevoegd moeten worden
	 * @param array $fields: velden waarvan er waarden van zullen ingevoegd worden
	 * @access public
	 * @author Hipska
	 */
	public function insert( $table, $fields = null){
		$sql = 'INSERT INTO ' . $table . ' ';
		if(!is_null($fields)){
			$sql .= '(' . implode(', ', $fields) . ') ';
		}
		return new self($sql);
	}
	
	/**
	 * Query::drop()
	 *
	 * Maak een DROP query.
	 *
	 * @param string $table: tabel die verwijdert moet worden
	 * @access public
	 * @author Hipska
	 */
	public function drop( $table ){
		return new self('DROP TABLE ' . $table );
	}
	
	/**
	 * Query::create()
	 *
	 * Maak een CREATE query.
	 * Niet af! Reden: te complex.
	 * 
	 * @param string $table: naam van de tabel die aangemaakt moet worden
	 * @access public
	 * @author Hipska
	 */
	public function create( $table ){
		return new self('CREATE TABLE ' . $table . ' ' );
	}
		
	
	/**
	 * Query::from()
	 *
	 * Kies met welke tabel(len) er gewerkt moet worden.
	 *
	 * @param mixed $tables: tabel(en) waarmee gewerkt moet worden
	 * @access public
	 * @author Hipska
	 */
	public function from( $tables ) {
		if(!is_array($tables)) $tables = func_get_args();
		$this->query .= 'FROM ' . implode( ', ', $tables ) . ' ';
		/* niet af
		foreach ($tables as $table) { //overloop de tabellen om een AS te zoeken
			
			$this->table[] = $table;
		}
		*/
		$this->tables = $tables;
		foreach ($this->tables as $t => $tname) {
			$this->query = str_ireplace('t'.($t+1).'.', $tname.'.', $this->query);
		}
		return $this;
	}
	
	/**
	 * Query::set()
	 *
	 * Stel de waarden van de velden om te updaten in.
	 * Hierbij zijn de keys van de array de naam van het veld
	 * en de values van de array zijn de in te stellen waarden.
	 *
	 * @param array $fields: de velden die je wil updaten
	 * @access public
	 * @author Hipska
	 */
	public function set( Array $fields ){
		$set = array();
		
		foreach ($fields as $field => $value) {
			$set[] = $field . " = '" . $value . "'";
		}
		
		$this->query .= 'SET ' . implode( ', ', $set) . ' ';
		return $this;
	}
	
	/**
	 * Query::values()
	 *
	 * Geef de waarden op om een rij mee in te voegen.
	 * Wil je meerdere rijen invoegen, dan kan je een 
	 * lijst van array's of een array van array's opgeven.
	 *
	 * @param array $valuelist: array met waarden om in te voegen
	 * @access public
	 * @author Hipska
	 */
	public function values( Array $valuelist ){
		
		$this->query .= 'VALUES ';
		$values = array();
		
		if( func_num_args() > 1 ){
			$valuelist = func_get_args();
		}
		
		foreach ($valuelist as $value) {
			$values[] = "( '" . implode("', '", $value) . "' )";
		}
		
		$this->query .= implode(', ', $values);
		return $this;
	}
	
	/**
	 * Query::where()
	 * 
	 * @param mixed $condition: de velden die moeten vergeleken worden
	 * @param string $operator: de operator voor deze vergelijkingen ( =, <, >, <=, >=, <>, .. )
	 * @param string $logic: de logische operator voor verschillende vergelijkininen (AND, OR)
	 * @access public
	 * @author Hipska
	 */
	public function where( $condition, $operator = '=', $logic = 'AND' ) {
		$conditions = array();
		if($operator == 'AND' or $operator == 'OR'){
			$logic = $operator;
			$operator = '=';
		}
		
		if(is_array($condition)){
			foreach( $condition as $column => $value ) {
				if(is_string($column)){
					$conditions[] = $column . ' ' . $operator . " '" . $value . "'";
					$prev_column = $column;
				}else{
					$conditions[] = $prev_column . ' ' . $operator . " '" . $value . "'";
				}
			}
		}else{
			$conditions = func_get_args();
		}
		
		if(count($conditions) <= 1) $this->query .= 'WHERE ' . implode( $logic . ' ', $conditions ) . ' ';
		else $this->query .= 'WHERE (' . implode(' ' . $logic . ' ', $conditions ) . ') ';
		
		return $this;
	}
	
	/**
	 * Query::or_condition()
	 * 
	 * @param mixed $condition: de velden die moeten vergeleken worden
	 * @param string $operator: de operator voor deze vergelijkingen ( =, <, >, <=, >=, <>, .. )
	 * @param string $logic: de logische operator voor verschillende vergelijkininen (AND, OR)
	 * @access public
	 * @author Hipska
	 */
	public function or_condition( $condition, $operator = '=', $logic = 'AND' ) {
		$conditions = array();
		if($operator == 'AND' or $operator == 'OR'){
			$logic = $operator;
			$operator = '=';
		}
		
		if(is_array($condition)){
			foreach( $condition as $column => $value ) {
				if(is_string($column)){
					$conditions[] = $column . ' ' . $operator . " '" . $value . "'";
					$prev_column = $column;
				}else{
					$conditions[] = $prev_column . ' ' . $operator . " '" . $value . "'";
				}
			}
		}else{
			$conditions = func_get_args();
		}
		
		if(count($conditions) <= 1) $this->query .= 'OR ' . implode( $logic . ' ', $conditions ) . ' ';
		else $this->query .= 'OR (' . implode(' ' . $logic . ' ', $conditions ) . ') ';
		
		return $this;
	}
	
	/**
	 * Query::and_condition()
	 * 
	 * @param mixed $condition: de velden die moeten vergeleken worden
	 * @param string $operator: de operator voor deze vergelijkingen ( =, <, >, <=, >=, <>, .. )
	 * @param string $logic: de logische operator voor verschillende vergelijkininen (AND, OR)
	 * @access public
	 * @author Hipska
	 */
	public function and_condition( $condition, $operator = '=', $logic = 'OR' ) {
		$conditions = array();
		if($operator == 'AND' or $operator == 'OR'){
			$logic = $operator;
			$operator = '=';
		}
		
		if(is_array($condition)){
			foreach( $condition as $column => $value ) {
				if(is_string($column)){
					$conditions[] = $column . ' ' . $operator . " '" . $value . "'";
					$prev_column = $column;
				}else{
					$conditions[] = $prev_column . ' ' . $operator . " '" . $value . "'";
				}
			}
		}else{
			$conditions = func_get_args();
		}
		
		if(count($conditions) <= 1) $this->query .= 'AND ' . implode( $logic . ' ', $conditions ) . ' ';
		else $this->query .= 'AND (' . implode(' ' . $logic . ' ', $conditions ) . ') ';
		
		return $this;
	}
	
	/**
	 * Query::join()
	 *
	 * Kies met met welke tabel en welke voorwaarde er gejoind moet worden.
	 *
	 * @param string $table: tabel waarmee gejoind moet worden
	 * @param string $cond1: veld van de eerste tabel om te vergelijken
	 * @param string $cond2: veld van de join-tabel om te vergelijken
	 * @param string $type: het type join (INNER, LEFT, RIGHT)
	 * @access public
	 * @author Hipska
	 */
	public function join( $table, $cond1, $cond2 = '', $type = '' ){
		$this->tables[] = $table; // add table to tables pool
		$this->query .= ltrim($type . ' JOIN '. $table . ' ');
		
		if( $cond2 == $cond1 or $cond2 == ''){
			$this->query .= 'USING ( ' . $cond1 . ' ) ';
		}else{
			$cond1 = (strpos($cond1, '.') === false)? $this->tables[0] . '.' . $cond1 : $cond1;
			$cond2 = (strpos($cond2, '.') === false)? $table . '.' . $cond2 : $cond2;
			
			$this->query .= 'ON ( ' . $cond1 . ' = ' . $cond2 . ' ) ';
		}
		
		foreach ($this->tables as $t => $tname) {
			$this->query = str_ireplace('t'.($t+1).'.', $tname.'.', $this->query);
		}
		return $this;
	}
	
	/**
	 * Query::union()
	 *
	 * Een query van de ene tabel met een query van een andere tabel samenvoegen
	 *
	 * @param mixed $all: true of 'all' om UNION ALL te doen, leeg of false om gewone UNION te doen
	 * @access public
	 * @author Hipska
	 */
	public function union($all = false){
		$this->query .= 'UNION ';
		if($all) $this->query .= 'ALL ';
		
		$this->query .= 'SELECT ' . implode( ', ', $this->fields) . ' ';
		
		return $this;
	}
	
	/**
	 * Query::limit()
	 *
	 * het aantal resultaten limiteren
	 * ( als rowcount leeg is, dan is offset het aantal rijen )
	 *
	 * @param int $offset: vanaf de hoeveelste rij
	 * @param int $rowcount: het aantal rijen
	 * @access public
	 * @author Hipska
	 */
	public function limit( $offset, $rowcount = true ){
		$this->query .= 'LIMIT ' . $offset;
		
		if($rowcount !== true){
			$this->query .= ', ' . $rowcount;
		}
		
		return $this;
	}
	
	/**
	 * Query::order()
	 *
	 * Stel in op welke velden gesorteerd moet worden.
	 * deze array heeft telkens als key het veld dat 
	 * gesorteerd moet worden en als value de volgorde
	 * (oplopend = ASC, aflopend = DESC)
	 *
	 * @param array $by: array met sorteervolgorden
	 * @access public
	 * @author Hipska
	 */
	public function order( Array $by ){
		$this->query .= 'ORDER BY ';
		$orders = array();
		foreach ($by as $field => $order) {
			$orders[] = $field . ' ' . $order;
		}
		$this->query .= implode( ', ', $orders) . ' ';
		return $this;
	}
}

?>

Reacties

0
Nog geen reacties.