Foreign, debug, datetime and ids
This commit is contained in:
parent
365f2ff580
commit
4fb305a1c2
|
@ -4,6 +4,8 @@ namespace Krutush\Database;
|
||||||
|
|
||||||
class Database{
|
class Database{
|
||||||
private $pdo;
|
private $pdo;
|
||||||
|
private $debug = false;
|
||||||
|
private $requests = [];
|
||||||
|
|
||||||
public function __construct(array $settings){
|
public function __construct(array $settings){
|
||||||
$dns = $settings['driver'] .
|
$dns = $settings['driver'] .
|
||||||
|
@ -12,6 +14,7 @@ class Database{
|
||||||
';dbname=' . $settings['schema'] .
|
';dbname=' . $settings['schema'] .
|
||||||
((isset($settings['charset'])) ? (';charset=' . $settings['charset']) : '');
|
((isset($settings['charset'])) ? (';charset=' . $settings['charset']) : '');
|
||||||
|
|
||||||
|
$this->debug = isset($settings['debug']) ? $settings['debug'] : false;
|
||||||
$this->pdo = new \PDO($dns, $settings['username'], $settings['password'], $settings['options']);
|
$this->pdo = new \PDO($dns, $settings['username'], $settings['password'], $settings['options']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +23,9 @@ class Database{
|
||||||
}
|
}
|
||||||
|
|
||||||
public function prepare(string $request){
|
public function prepare(string $request){
|
||||||
|
if($this->debug)
|
||||||
|
$this->requests[] = $request;
|
||||||
|
|
||||||
return $this->pdo->prepare($request);
|
return $this->pdo->prepare($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,8 +78,12 @@ class Database{
|
||||||
return $drop;
|
return $drop;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLastInsertId(){
|
public function getLastInsertId(): int{
|
||||||
return $this->pdo->lastInsertId();
|
return $this->pdo->lastInsertId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getRequests(): array{
|
||||||
|
return $this->requests;
|
||||||
|
}
|
||||||
//TODO update, delete
|
//TODO update, delete
|
||||||
}
|
}
|
|
@ -14,9 +14,15 @@ class Model{
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public const TABLE = null;
|
public const TABLE = null;
|
||||||
|
|
||||||
/** @var array
|
/** @var array */
|
||||||
* @example ['id' => ['column' => 'idColumn', 'type' => 'int', 'not_null' => true, 'primary' => true, 'custom' => 'AUTO_INCREMENT']] */
|
|
||||||
public const FIELDS = [];
|
public const FIELDS = [];
|
||||||
|
/*[
|
||||||
|
'id' => ['column' => 'idColumn', 'type' => 'int', 'not_null' => true, 'primary' => true, 'custom' => 'AUTO_INCREMENT'],
|
||||||
|
'owner' => ['type' => 'int', 'foreign' => ['model' => UserModel::class, 'field' => 'id', 'on_delete' => 'cascade', 'on_update' => 'set null']]
|
||||||
|
]*/
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public const ID = 'id';
|
||||||
|
|
||||||
/** @var array
|
/** @var array
|
||||||
* @example ['id' => ['value' => 1, 'modified' => false]] */
|
* @example ['id' => ['value' => 1, 'modified' => false]] */
|
||||||
|
@ -127,6 +133,10 @@ class Model{
|
||||||
return isset($options['column']) ? $options['column'] : $field;
|
return isset($options['column']) ? $options['column'] : $field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getID(): string{
|
||||||
|
return static::getColumn(static::ID);
|
||||||
|
}
|
||||||
|
|
||||||
public static function getColumns(bool $sql = true): array{
|
public static function getColumns(bool $sql = true): array{
|
||||||
$fields = static::getFields();
|
$fields = static::getFields();
|
||||||
$columns = [];
|
$columns = [];
|
||||||
|
@ -172,11 +182,19 @@ class Model{
|
||||||
public function getModifiedValues(){
|
public function getModifiedValues(){
|
||||||
$values = [];
|
$values = [];
|
||||||
foreach ($this->fields as $field => $data) {
|
foreach ($this->fields as $field => $data) {
|
||||||
if($data['modified']) $values[] = $data['value'];
|
if($data['modified'])
|
||||||
|
$values[] = $data['value'];
|
||||||
|
|
||||||
}
|
}
|
||||||
return $values;
|
return $values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function unmodify(){
|
||||||
|
foreach($this->fields as $field => $data){
|
||||||
|
$this->fields[$field]['modified'] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function getPrimaryValues(){
|
public function getPrimaryValues(){
|
||||||
$values = [];
|
$values = [];
|
||||||
foreach ($this->fields as $field => $data) {
|
foreach ($this->fields as $field => $data) {
|
||||||
|
@ -207,6 +225,15 @@ class Model{
|
||||||
case 'bit':
|
case 'bit':
|
||||||
$data = boolval($data); //MAYBE: E_NOTICE on strange types
|
$data = boolval($data); //MAYBE: E_NOTICE on strange types
|
||||||
break;
|
break;
|
||||||
|
case 'date':
|
||||||
|
$data = (is_a($data, \DateTime::class) ? $data : new \DateTime(strval($data)))->format('Y-m-d');
|
||||||
|
break;
|
||||||
|
case 'time':
|
||||||
|
$data = (is_a($data, \DateTime::class) ? $data : new \DateTime(strval($data)))->format('H:i:s');
|
||||||
|
break;
|
||||||
|
case 'datetime':
|
||||||
|
$data = (is_a($data, \DateTime::class) ? $data : new \DateTime(strval($data)))->format('Y-m-d H:i:s');
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new DatabaseException('unknown type in field : '.$field);
|
throw new DatabaseException('unknown type in field : '.$field);
|
||||||
break;
|
break;
|
||||||
|
@ -244,8 +271,13 @@ class Model{
|
||||||
return $req;
|
return $req;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function runInsert(){
|
public function runInsert(bool $forceID = true){
|
||||||
return static::insert()->run($this->getValues());
|
$insert = static::insert();
|
||||||
|
$res = $insert->run($this->getValues());
|
||||||
|
if($forceID)
|
||||||
|
$this->{static::ID} = Connection::get(static::DATABASE)->getLastInsertID();
|
||||||
|
|
||||||
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function runUpdate(){
|
public function runUpdate(){
|
||||||
|
@ -253,7 +285,9 @@ class Model{
|
||||||
->update(static::getModifiedColumns())
|
->update(static::getModifiedColumns())
|
||||||
->table(static::TABLE)
|
->table(static::TABLE)
|
||||||
->where(implode(' AND ', array_map(function($field){ return $field.' = ?'; }, static::getPrimaryColumns())))
|
->where(implode(' AND ', array_map(function($field){ return $field.' = ?'; }, static::getPrimaryColumns())))
|
||||||
->run(array_merge($this->getModifiedValues(), $this->getPrimaryValues()));
|
->run(array_merge($this->getModifiedValues(true), $this->getPrimaryValues()));
|
||||||
|
$this->unmodify();
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function create(): Request\Create{
|
public static function create(): Request\Create{
|
||||||
|
@ -261,14 +295,42 @@ class Model{
|
||||||
->create(static::TABLE);
|
->create(static::TABLE);
|
||||||
|
|
||||||
foreach (static::getFields() as $field => $options) {
|
foreach (static::getFields() as $field => $options) {
|
||||||
|
$column = static::getColumn($field);
|
||||||
$req->column(
|
$req->column(
|
||||||
static::getColumn($field),
|
$column,
|
||||||
$options['type'],
|
$options['type'],
|
||||||
isset($options['lenght']) ? $options['lenght'] : null,
|
isset($options['lenght']) ? $options['lenght'] : null,
|
||||||
isset($options['not_null']) && $options['not_null'],
|
isset($options['not_null']) && $options['not_null'],
|
||||||
isset($options['primary']) && $options['primary'],
|
|
||||||
isset($options['unique']) && $options['unique'],
|
|
||||||
isset($options['custom']) ? $options['custom'] : null);
|
isset($options['custom']) ? $options['custom'] : null);
|
||||||
|
|
||||||
|
if(isset($options['primary']) && $options['primary'])
|
||||||
|
$req->primary($column);
|
||||||
|
|
||||||
|
if(isset($options['unique']) && $options['unique'])
|
||||||
|
$req->unique($column);
|
||||||
|
|
||||||
|
if(isset($options['foreign'])){
|
||||||
|
$foreign = $options['foreign'];
|
||||||
|
|
||||||
|
$model = null;
|
||||||
|
|
||||||
|
if(is_array($foreign)){
|
||||||
|
if(!isset($foreign['model']))
|
||||||
|
throw new DatabaseException('Any model for foreign in field '.$field);
|
||||||
|
|
||||||
|
$model = $foreign['model'];
|
||||||
|
}else{
|
||||||
|
$model = $foreign;
|
||||||
|
}
|
||||||
|
if(!class_exists($model))
|
||||||
|
throw new DatabaseException('Can\'t find class '.$model.' for foreign in field '.$field);
|
||||||
|
|
||||||
|
$req->foreign($column, $model::TABLE,
|
||||||
|
$model::getColumn(isset($foreign['field']) ? $foreign['field'] : $model::ID),
|
||||||
|
isset($foreign['index']) ? $foreign['index'] : true,
|
||||||
|
isset($foreign['on_delete']) ? $foreign['on_delete'] : null,
|
||||||
|
isset($foreign['on_update']) ? $foreign['on_update'] : null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $req;
|
return $req;
|
||||||
|
@ -325,13 +387,11 @@ class Model{
|
||||||
return $data['count'];
|
return $data['count'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function find($id): ?self{
|
||||||
/* TODO: Manager ids
|
|
||||||
public static function find($id) {
|
|
||||||
return static::first(array($id), (static::getID().' = ?'));
|
return static::first(array($id), (static::getID().' = ?'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function findOrFail($id) {
|
public static function findOrFail($id): self{
|
||||||
return static::firstOrFail(array($id), (static::getID().' = ?'));
|
return static::firstOrFail(array($id), (static::getID().' = ?'));
|
||||||
}*/
|
}
|
||||||
}
|
}
|
|
@ -10,19 +10,49 @@ class Create extends Request{
|
||||||
protected $columns = [];
|
protected $columns = [];
|
||||||
protected $primary = [];
|
protected $primary = [];
|
||||||
protected $unique = [];
|
protected $unique = [];
|
||||||
|
protected $index = [];
|
||||||
|
protected $foreign = [];
|
||||||
|
|
||||||
public function table(string $table): Create{
|
public function table(string $table): Create{
|
||||||
$this->table = $table;
|
$this->table = $table;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function column(string $name, string $type, int $lenght = null, bool $not_null = false, bool $primary = false, bool $unique = false, string $more = null): Create{
|
public function column(string $name, string $type, int $lenght = null, bool $not_null = false, string $more = null): Create{ //Really ?
|
||||||
$this->columns[] = '`'.$name.'` '.$type.($lenght ? '('.$lenght.')' : '').($not_null ? ' NOT NULL' : '').(isset($more) ? ' '.$more : '');
|
$this->columns[] = '`'.$name.'` '.$type.($lenght ? '('.$lenght.')' : '').($not_null ? ' NOT NULL' : '').(isset($more) ? ' '.$more : '');
|
||||||
if($primary)
|
return $this;
|
||||||
$this->primary[] = '`'.$name.'`';
|
}
|
||||||
|
|
||||||
if($unique)
|
public function primary(string $name): Create{
|
||||||
$this->unique[$name] = [$name];
|
$this->primary[] = '`'.$name.'`';
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unique(string $name): Create{
|
||||||
|
$this->unique[$name] = ['`'.$name.'`'];
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function uniques(string $name, array $columns): Create{
|
||||||
|
$this->unique[$name] = [$columns];
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index(string $name): Create{
|
||||||
|
$this->index[$name] = ['`'.$name.'`'];
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function indexs(string $name, array $columns): Create{
|
||||||
|
$this->index[$name] = [$columns];
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function foreign(string $name, string $table, string $column, bool $index = true, string $on_delete = null, string $on_update = null): Create{ //TODO: complex foreign
|
||||||
|
if($index)
|
||||||
|
$this->index($name);
|
||||||
|
|
||||||
|
$this->foreign[$name] = compact('name', 'table', 'column', 'on_delete', 'on_update');
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +65,19 @@ class Create extends Request{
|
||||||
|
|
||||||
$uniques = [];
|
$uniques = [];
|
||||||
foreach ($this->unique as $name => $columns) {
|
foreach ($this->unique as $name => $columns) {
|
||||||
$uniques[] = 'CONSTRAINT UC_'.ucfirst(strtolower($name)).' UNIQUE ('.implode(', ', $columns).')';
|
$uniques[] = 'CONSTRAINT `UQ_'.ucfirst(strtolower($this->table)).'_'.ucfirst(strtolower($name)).'` UNIQUE ('.implode(', ', $columns).')';
|
||||||
|
}
|
||||||
|
|
||||||
|
$indexs = [];
|
||||||
|
foreach ($this->index as $name => $columns) {
|
||||||
|
$indexs[] = 'INDEX `ID_'.ucfirst(strtolower($this->table)).'_'.ucfirst(strtolower($name)).'` ('.implode(', ', $columns).')';
|
||||||
|
}
|
||||||
|
|
||||||
|
$foreigns = [];
|
||||||
|
foreach ($this->foreign as $name => $options) {
|
||||||
|
$foreigns[] = 'CONSTRAINT `FK_'.ucfirst(strtolower($this->table)).'_'.ucfirst(strtolower($name)).'` FOREIGN KEY (`'.$options['name'].'`) REFERENCES `'.$options['table'].'` (`'.$options['column'].'`)'.
|
||||||
|
(isset($options['on_delete']) ? 'ON DELETE '.$options['on_delete'] : '').
|
||||||
|
(isset($options['on_update']) ? 'ON UPDATE '.$options['on_update'] : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'CREATE TABLE `'.$this->table.'`('."\n".
|
return 'CREATE TABLE `'.$this->table.'`('."\n".
|
||||||
|
@ -43,9 +85,11 @@ class Create extends Request{
|
||||||
array_merge(
|
array_merge(
|
||||||
$this->columns,
|
$this->columns,
|
||||||
(empty($this->primary) ? [] : [
|
(empty($this->primary) ? [] : [
|
||||||
'CONSTRAINT PK_'.ucfirst(strtolower(strtok($this->table, ' '))).' PRIMARY KEY ('.implode(', ', $this->primary).')'
|
'CONSTRAINT `PK_'.ucfirst(strtolower(strtok($this->table, ' '))).'` PRIMARY KEY ('.implode(', ', $this->primary).')'
|
||||||
]),
|
]),
|
||||||
$uniques
|
$indexs,
|
||||||
|
$uniques,
|
||||||
|
$foreigns
|
||||||
)
|
)
|
||||||
)."\n)";
|
)."\n)";
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace Krutush\Database\Request;
|
||||||
|
|
||||||
use Krutush\Database\Database;
|
use Krutush\Database\Database;
|
||||||
|
|
||||||
class Request{
|
class Request{ //TODO: escape and slugify
|
||||||
protected $db;
|
protected $db;
|
||||||
|
|
||||||
public function __construct(Database $db){
|
public function __construct(Database $db){
|
||||||
|
|
Loading…
Reference in New Issue