Last active
October 20, 2016 08:49
-
-
Save nimmneun/a2095e05203548ba0756 to your computer and use it in GitHub Desktop.
Simple MySQL query builder
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php namespace MonoQuery; | |
/** | |
* Uber simple single table query builder. | |
* | |
* @author neun | |
* @since 27.09.2015 15:35 | |
*/ | |
class Query | |
{ | |
private $table; | |
private $type; | |
private $limit; | |
private $order; | |
private $sql; | |
private $wheres = []; | |
private $values = []; | |
private $columns = []; | |
private $inserts = []; | |
private $joins = []; | |
private $stms = [ | |
'select' => "SELECT\n %3\$s\nFROM\n `%1\$s`\nWHERE %2\$s\n%5\$s\n%6\$s", | |
'insert' => "INSERT INTO\n `%1\$s`\n (%3\$s)\nVALUES\n (%4\$s)", | |
'update' => "UPDATE\n `%1\$s`\nSET %3\$s\nWHERE %2\$s", | |
'delete' => "DELETE FROM\n `%1\$s`\nWHERE %2\$s", | |
]; | |
private function __construct($table, $type) | |
{ | |
$this->table = $table; | |
$this->type = $type; | |
} | |
/** | |
* Query::from('user')->select(['id', 'email'])->where('id')->equals('1') | |
* | |
* @param string $table | |
* @return Query | |
*/ | |
public static function from($table) | |
{ | |
return new Query($table, 'select'); | |
} | |
/** | |
* Query::insert('user')->values([]) | |
* | |
* @param string $table | |
* @return Query | |
*/ | |
public static function insert($table) | |
{ | |
return new Query($table, 'insert'); | |
} | |
/** | |
* Query::update('user')->set([])->where('id')->equals('1') | |
* | |
* @param string $table | |
* @return Query | |
*/ | |
public static function update($table) | |
{ | |
return new Query($table, 'update'); | |
} | |
/** | |
* Query::delete('user')->where('id')->equals(6) | |
* | |
* @param string $table | |
* @return Query | |
*/ | |
public static function delete($table) | |
{ | |
return new Query($table, 'delete'); | |
} | |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
/** | |
* @param array $args | |
* @return Query | |
*/ | |
public function innerJoin($args) | |
{ | |
$join = "INNER JOIN\n "; | |
$this->buildJoins($args, $join); | |
return $this; | |
} | |
/** | |
* @param array $args | |
* @return Query | |
*/ | |
public function leftJoin($args) | |
{ | |
$join = "LEFT JOIN\n "; | |
$this->buildJoins($args, $join); | |
return $this; | |
} | |
/** | |
* @param array $columns | |
* @return Query | |
*/ | |
public function select(array $columns) | |
{ | |
foreach ($columns as $column) { | |
list($table, $field) = self::split($column); | |
$table = null !== $table ? self::escape($table).'.' : null; | |
$field = $field != '*' ? self::escape($field) : '*'; | |
$this->columns[] = $table.$field; | |
} | |
return $this; | |
} | |
/** | |
* @param string $column | |
* @param string $andOr | |
* @return Query | |
*/ | |
public function where($column, $andOr = 'AND') | |
{ | |
$table = null; | |
if (false !== strpos($column, '.')) { | |
list ($table, $column) = explode('.', $column); | |
$table = self::escape($table).'.'; | |
} | |
$this->wheres[] = 0 !== count($this->values) | |
? "\n ".$andOr." ".$table.self::escape($column) | |
: "\n ".$table.self::escape($column); | |
return $this; | |
} | |
/** | |
* @param array $values | |
* @return Query | |
*/ | |
public function values(array $values) | |
{ | |
foreach ($values as $column => $value) { | |
$this->columns[] = self::escape($column); | |
$this->inserts[] = self::quote($value); | |
} | |
return $this; | |
} | |
/** | |
* @param array $values | |
* @return Query | |
*/ | |
public function set(array $values) | |
{ | |
foreach ($values as $column => $value) { | |
$this->columns[] = "\n ".self::escape($column).' = '.self::quote($value); | |
} | |
return $this; | |
} | |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
/** | |
* @param string $value | |
* @return Query | |
*/ | |
public function equals($value) | |
{ | |
$this->values[] = array_pop($this->wheres).' = '.self::quote($value); | |
return $this; | |
} | |
/** | |
* @param string $value | |
* @return Query | |
*/ | |
public function greater($value) | |
{ | |
$this->values[] = array_pop($this->wheres).' > '.self::quote($value); | |
return $this; | |
} | |
/** | |
* @param string $value | |
* @return Query | |
*/ | |
public function lesser($value) | |
{ | |
$this->values[] = array_pop($this->wheres).' < '.self::quote($value); | |
return $this; | |
} | |
/** | |
* @param string $value | |
* @return Query | |
*/ | |
public function like($value) | |
{ | |
$this->values[] = array_pop($this->wheres).' LIKE '.self::quote($value); | |
return $this; | |
} | |
/** | |
* @param string $value1 | |
* @param string $value2 | |
* @return Query | |
*/ | |
public function between($value1, $value2) | |
{ | |
$this->values[] = array_pop($this->wheres).' BETWEEN ' | |
.self::quote($value1).' AND ' | |
.self::quote($value2); | |
return $this; | |
} | |
/** | |
* @param string $value1 | |
* @param string $value2 | |
* @return Query | |
*/ | |
public function notBetween($value1, $value2) | |
{ | |
$this->values[] = array_pop($this->wheres).' NOT BETWEEN ' | |
.self::quote($value1).' AND ' | |
.self::quote($value2); | |
return $this; | |
} | |
/** | |
* @param string $limit | |
* @return Query | |
*/ | |
public function limit($limit = null) | |
{ | |
$this->limit = null === $limit ? '' : 'LIMIT '.$limit; | |
return $this; | |
} | |
/** | |
* @param string $order | |
* @param string $dir | |
* @return Query | |
*/ | |
public function orderBy($order = null, $dir = 'ASC') | |
{ | |
$this->order = null === $order ? '' : 'ORDER BY '.self::escape($order).' '.$dir; | |
return $this; | |
} | |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
/** | |
* @return string | |
*/ | |
public function build() | |
{ | |
if (0 !== count($this->joins)) { | |
$joins = ''; | |
foreach ($this->joins as $join) { | |
$joins .= $join; | |
} | |
$this->stms[$this->type] = str_replace('WHERE', $joins.'WHERE', $this->stms[$this->type]); | |
} | |
$this->sql = preg_replace( | |
"/\n+/", "\n", | |
sprintf($this->stms[$this->type], | |
$this->table, | |
implode(' ', $this->values), | |
implode(', ', $this->columns), | |
implode(', ', $this->inserts), | |
$this->order, | |
$this->limit | |
) | |
); | |
return $this->sql; | |
} | |
/** | |
* @param \PDO $pdo | |
* @return \PDOStatement | |
*/ | |
public function run(\PDO $pdo) | |
{ | |
if (0 === strlen($this->sql)) { | |
$this->build(); | |
} | |
return $pdo->query($this->sql); | |
} | |
/** | |
* Nasty quick and dirty solution *lol | |
* | |
* @param array $args | |
* @param string $join | |
*/ | |
private function buildJoins($args, $join) | |
{ | |
$table = null; | |
foreach ($args as $field1 => $field2) { | |
list($table1, $column1) = self::split($field1); | |
list($table2, $column2) = self::split($field2); | |
if (!isset($table)) { | |
$table = $table2; | |
} | |
if (false === strpos($join, ' ON ')) { | |
$join .= self::escape($table2).' ON '; | |
} else { | |
$join .= ' AND '; | |
} | |
$join .= self::escape($table1).'.'.self::escape($column1); | |
if (null === $table2) { | |
$join .= ' = '.self::quote($column2); | |
} else { | |
$join .= ' = '.self::escape($table2).'.'.self::escape($column2); | |
} | |
} | |
$this->joins[$table] = $join."\n"; | |
} | |
/** | |
* @param string $string | |
* @return string | |
*/ | |
private static function escape($string) | |
{ | |
return '`'.$string.'`'; | |
} | |
/** | |
* @param string $string | |
* @return string | |
*/ | |
private static function quote($string) | |
{ | |
return '\''.str_replace(['\''], ['\\\''], $string).'\''; | |
} | |
/** | |
* @param string $value | |
* @return array | |
*/ | |
private static function split($value) | |
{ | |
return 2 === count($tmp = explode('.', $value)) ? $tmp : [null, $value]; | |
} | |
} |
Author
nimmneun
commented
Sep 27, 2015
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment