big updat

larg
This commit is contained in:
Malloc of Kuzkycyziklistan 2017-02-28 15:46:54 -06:00
parent 6edc85b731
commit 4fd5e5fbd9
10 changed files with 190 additions and 70 deletions

View file

@ -13,7 +13,7 @@ class Configuration {
if(self::$data != null)
return;
self::$data = parse_ini_string($data);
self::$data = parse_ini_string($data, true);
}
public static function section(string $name): ConfigSection {

View file

@ -10,6 +10,7 @@ class Database {
/** @var \PDO */
private static $dbConn;
private static $queries = [];
private static $batchQueue = [];
public static function initialize() {
self::$dbConn = new \PDO(
@ -17,16 +18,36 @@ class Database {
conf::section(AMVC_CNF_DB)->value(AMVC_CNF_DB_USER),
conf::section(AMVC_CNF_DB)->value(AMVC_CNF_DB_PASS)
);
self::$dbConn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
}
public static function select($columns): Selectable {
return new Selectable($columns);
public static function select($columns, $model = null): Selectable {
return new Selectable($columns, $model);
}
public static function update($table): Modifiable {
return new Modifiable($table);
}
public static function insert($table): Insertable {
return new Insertable($table);
}
public static function delete($table): Deletable {
return new Deletable($table);
}
public static function batchQuery(Queryable $query) {
self::getStatement($query->getRawQuery());
$batchQueue[] = [self::hashQuery($query->getRawQuery()), $query->getParams()];
}
public static function rawQuery(string $query, $params = null, int $type = AMVC_DB_FETCH_ROWS): array {
$stmt = self::getStatement($query);
foreach($params as $name => $param)
$stmt->bindParam(":$name", $param);
$stmt->execute();
switch($type) {
@ -76,4 +97,18 @@ class Database {
return md5($query);
}
protected static function updateDatabase() {
self::$dbConn->beginTransaction();
foreach(self::$batchQueue as $query) {
$stmt = self::getStatement($query[0]);
foreach($query[1] as $name => $param)
$stmt->bindValue(":$name", $param);
$stmt->execute();
}
self::$dbConn->commit();
self::$batchQueue = [];
}
}

6
AroMVC/Deletable.php Normal file
View file

@ -0,0 +1,6 @@
<?php
namespace AroMVC\Core;
class Deletable extends Queryable {
}

View file

@ -1,12 +1,16 @@
<?php
namespace AroMVC\Core;
use AroMVC\Core\Database as db;
abstract class Model {
protected $rawData = [];
protected $associations = [];
protected $hooks = [];
protected static $table = null;
protected $index = "id";
protected $deleted = false;
protected $modified = [];
public function __construct() {}
public static function withId(int $id) {
@ -25,6 +29,9 @@ abstract class Model {
}
protected abstract function initialize();
protected function setTable(string $tableName) {
$this->table = $tableName;
}
protected function get(string $name) {
return $this->rawData[$name];
@ -61,11 +68,15 @@ abstract class Model {
$this->associations[strtolower($associationName)] = strtolower($rawName);
}
protected function update() {
public static function select(): Selectable {
return db::select("*", new static)->from(self::$table);
}
public function update() {
}
protected function delete() {
public function delete() {
}
}

6
AroMVC/Modifiable.php Normal file
View file

@ -0,0 +1,6 @@
<?php
namespace AroMVC\Core;
class Modifiable extends Queryable {
}

View file

@ -18,6 +18,14 @@ abstract class Queryable {
$this->results = db::rawRowQuery($this->query, $this->params);
}
public function getRawQuery() {
return $this->query;
}
public function getParams() {
return $this->params;
}
/*protected function allowConditionals(bool $allow) {
if($allow)
$this->setFlag(AMVC_QRY_CNDLS);
@ -60,4 +68,9 @@ abstract class Queryable {
protected function unlock(int $lock) {
$this->locks &= ~$lock;
}
protected function testLocked() {
if($this->locks != 0)
throw new \Exception("Query is locked from previous step and cannot proceed (LOCKVAL $this->locks)");
}
}

View file

@ -12,9 +12,9 @@ define("AMVC_QRY_SEL_HAVING", 5);
define("AMVC_QRY_SEL_ORDER", 6);
define("AMVC_QRY_SEL_LIMIT", 7);
// TODO allow appending and rewriting of existing data in a query from any point
class Selectable extends Queryable {
/** @var null|\ReflectionClass */
protected $model = null;
protected $components = [
AMVC_QRY_SEL_COLS => [],
AMVC_QRY_SEL_FROM => null,
@ -26,7 +26,22 @@ class Selectable extends Queryable {
AMVC_QRY_SEL_LIMIT => null
];
public function __construct($selection) {
protected function getModelReflection($model): \ReflectionClass {
$type = new \ReflectionClass($model);
if(!$type->isSubclassOf("\\AroMVC\\Core\\AroModel"))
throw new \Exception("Cannot instantiate non-model object.");
return $type;
}
protected function isEmpty(int $component): bool {
return count($this->components[$component]) == 0;
}
public function __construct($selection, $model = null) {
if($model != null)
$this->model = $this->getModelReflection($model);
if(!is_array($selection))
$selection = [$selection];
@ -34,10 +49,9 @@ class Selectable extends Queryable {
}
public function execute(): Selectable {
if($this->checkFlag(AMVC_QRY_SEL_NEEDON))
throw new \Exception("JOIN clause declared in query with no matching ON or USING clause");
$this->testLocked();
if($this->checkFlag(AMVC_QRY_SEL_GROUP) && !$this->checkFlag(AMVC_QRY_SEL_ORDER)) {
/*if($this->checkFlag(AMVC_QRY_SEL_GROUP) && !$this->checkFlag(AMVC_QRY_SEL_ORDER)) {
if($this->checkFlag(AMVC_QRY_SEL_HAVING)) {
$having = array_search("HAVING", $this->query);
array_splice($this->query, $having + 2, 0, ["ORDER BY", "null"]);
@ -45,103 +59,133 @@ class Selectable extends Queryable {
$group = array_search("GROUP BY", $this->query);
array_splice($this->query, $group + 2, 0, ["ORDER BY", "null"]);
}
}*/
$query = [
"SELECT",
implode(",", $this->components[AMVC_QRY_SEL_COLS]),
"FROM",
"`". $this->components[AMVC_QRY_SEL_FROM] ."`"
];
foreach($this->components[AMVC_QRY_SEL_JOINS] as $join)
array_push($query, implode(" ", $join));
if(!$this->isEmpty(AMVC_QRY_SEL_WHERE)) {
$wheres = array_map(function($x) {
return "($x)";
}, $this->components[AMVC_QRY_SEL_WHERE]);
array_push($query, "WHERE", implode(" AND ", $wheres));
}
if(!$this->isEmpty(AMVC_QRY_SEL_GROUP))
array_push($query, "GROUP BY", implode(", ", $this->components[AMVC_QRY_SEL_GROUP]));
if(!$this->isEmpty(AMVC_QRY_SEL_HAVING)) {
$haves = array_map(function($x) {
return "($x)";
}, $this->components[AMVC_QRY_SEL_HAVING]);
array_push($query, "HAVING", implode(" AND ", $haves));
}
if(!$this->isEmpty(AMVC_QRY_SEL_ORDER))
array_push($query, "ORDER BY", implode(", ", $this->components[AMVC_QRY_SEL_GROUP]));
if($this->components[AMVC_QRY_SEL_LIMIT] != null)
array_push($query, "LIMIT", $this->components[AMVC_QRY_SEL_LIMIT[0]] .",". $this->components[AMVC_QRY_SEL_LIMIT[1]]);
$this->query = implode(" ", $query);
parent::execute();
return $this;
}
public function from(string $where): Selectable {
$this->testLocked();
if($this->components[AMVC_QRY_SEL_FROM] != null)
throw new \Exception("Cannot redefine FROM clause after first definition");
array_push($this->query, "FROM", $where);
$this->components[AMVC_QRY_SEL_FROM] = $where;
return $this;
}
public function columns($columns): Selectable {
$this->testLocked();
if(!is_array($columns))
$columns = [$columns];
$this->components[AMVC_QRY_SEL_COLS] = $columns;
return $this;
}
public function join(string $type, string $table): Selectable {
if($this->checkPast(AMVC_QRY_SEL_JOINS))
throw new \Exception("Invalid JOIN clause, must proceed FROM clause");
$this->setFlag(AMVC_QRY_SEL_JOINS);
$this->setFlag(AMVC_QRY_SEL_NEEDON);
array_push($this->query, $type, $table);
$this->testLocked();
$this->lock(AMVC_QRY_SEL_LCK_JOIN);
array_push($this->components[AMVC_QRY_SEL_JOINS], [$type, $table]);
return $this;
}
public function on(string $condition): Selectable {
if(!$this->checkFlag(AMVC_QRY_SEL_NEEDON))
throw new \Exception("Cannot declare ON clause without prior JOIN clause");
if(!$this->checkLock(AMVC_QRY_SEL_LCK_JOIN))
throw new \Exception("ON subclause can only follow a JOIN clause");
$this->clearFlag(AMVC_QRY_SEL_NEEDON);
array_push($this->query, "ON", $condition);
$join = array_merge(
array_pop($this->components[AMVC_QRY_SEL_JOINS]),
["ON", $condition]
);
array_push($this->components[AMVC_QRY_SEL_JOINS], $join);
$this->unlock(AMVC_QRY_SEL_LCK_JOIN);
return $this;
}
public function using($columns): Selectable {
if(!$this->checkFlag(AMVC_QRY_SEL_NEEDON))
throw new \Exception("Cannot declare USING clause without prior JOIN clause");
if(!$this->checkLock(AMVC_QRY_SEL_LCK_JOIN))
throw new \Exception("USING subclause can only follow a JOIN clause");
if(is_array($columns))
$columns = implode(",", $columns);
$this->clearFlag(AMVC_QRY_SEL_NEEDON);
array_push($this->query, "USING", "({$columns})");
$join = array_merge(
array_pop($this->components[AMVC_QRY_SEL_JOINS]),
["USING", "($columns)"]
);
array_push($this->components[AMVC_QRY_SEL_JOINS], $join);
$this->unlock(AMVC_QRY_SEL_LCK_JOIN);
return $this;
}
public function where(string $condition): Selectable {
$this->checkFrom();
if($this->checkForOrPast(AMVC_QRY_SEL_WHERE))
throw new \Exception("Duplicate or misplaced WHERE clause in SELECT query");
$this->setFlag(AMVC_QRY_SEL_WHERE);
array_push($this->query, "WHERE", $condition);
$this->testLocked();
array_push($this->components[AMVC_QRY_SEL_WHERE], $condition);
return $this;
}
public function groupBy($columns): Selectable {
$this->checkFrom();
if($this->checkForOrPast(AMVC_QRY_SEL_GROUP))
throw new \Exception("Duplicate or misplaced GROUP BY clause in SELECT query");
$this->testLocked();
if(is_array($columns))
$columns = implode(",", $columns);
$this->setFlag(AMVC_QRY_SEL_GROUP);
array_push($this->query, "GROUP BY", $columns);
array_push($this->components[AMVC_QRY_SEL_GROUP], $columns);
return $this;
}
public function having(string $condition): Selectable {
$this->checkFrom();
if($this->checkForOrPast(AMVC_QRY_SEL_HAVING))
throw new \Exception("Duplicate or misplaced HAVING clause in SELECT query");
array_push($this->query, "HAVING", $condition);
$this->testLocked();
array_push($this->components[AMVC_QRY_SEL_HAVING], $condition);
return $this;
}
public function orderBy($columns): Selectable {
$this->checkFrom();
if($this->checkForOrPast(AMVC_QRY_SEL_ORDER))
throw new \Exception("Duplicate or misplaced ORDER BY clause in SELECT query");
$this->testLocked();
if(!is_array($columns))
$columns = [$columns];
if(is_array($columns))
$columns = implode(",", $columns);
$this->setFlag(AMVC_QRY_SEL_ORDER);
array_push($this->query, "ORDER BY", $columns);
array_push($this->components[AMVC_QRY_SEL_ORDER], $columns);
return $this;
}
public function limit(int $count, int $offset = 0): Selectable {
$this->checkFrom();
if($this->checkForOrPast(AMVC_QRY_SEL_LIMIT))
throw new \Exception("Duplicate or misplaced LIMIT clause in SELECT query");
$this->setFlag(AMVC_QRY_SEL_LIMIT);
array_push($this->query, "LIMIT", "$offset,$count");
$this->testLocked();
$this->components[AMVC_QRY_SEL_LIMIT] = [$offset, $count];
return $this;
}
@ -152,15 +196,14 @@ class Selectable extends Queryable {
return $this->results;
}
public function asModels($obj) {
public function asModels($model = null) {
if($this->results == null)
throw new \Exception("Cannot return results from a query that has not executed.");
$type = new \ReflectionClass($obj);
if(!$type->isSubclassOf("\\AroMVC\\Core\\AroModel"))
throw new \Exception("Cannot instantiate non-model object.");
if($this->model == null || $model != null)
$this->model = $this->getModelReflection($model);
foreach($this->results as $result)
yield $type->getMethod("withRow")->invoke(null, $result);
yield $this->model->getMethod("withRow")->invoke(null, $result);
}
}

View file

@ -3,6 +3,8 @@ namespace AroMVC\Models;
use \AroMVC\Core\Model;
class State extends Model {
protected static $table = "State";
protected $id;
protected $name;

View file

@ -1,4 +1,4 @@
[Database]
dsn = "mysql:host=localhost;dbname=fire"
username = "squidlord"
dsn = "mysql:host=localhost;dbname=test"
username = "root"
password = ""

View file

@ -1,5 +1,6 @@
<?php
namespace AroMVC;
use AroMVC\Core\Configuration;
use AroMVC\Core\Database;
use AroMVC\Core\Selectable;
use AroMVC\Models\Company;
@ -22,14 +23,17 @@ spl_autoload_register(function($class) {
}
});
// TODO write error handler
Configuration::initialize(file_get_contents("conf.ini"));
Database::initialize();
/*$tmp = new Selectable("*");
$tmp = new Selectable("*");
$tmp->from("Companies")
->where("`name` = ?")
->or("`id` = ?")
->where("`name` = :name OR `id` = :cid")
->params(["name" => "winco", "cid" => 20])
->join("LEFT JOIN", "Invoices")
->using("id")
->execute()
->asModels(new Company);*/
->asModels(new Company);