From 4fb305a1c24f4afb749184c8b4353bfaa8ad4528 Mon Sep 17 00:00:00 2001 From: sheychen Date: Sun, 13 May 2018 13:43:45 +0200 Subject: [PATCH] Foreign, debug, datetime and ids --- src/Database.php | 12 +++++- src/Model.php | 88 ++++++++++++++++++++++++++++++++++------- src/Request/Create.php | 60 ++++++++++++++++++++++++---- src/Request/Request.php | 2 +- 4 files changed, 138 insertions(+), 24 deletions(-) diff --git a/src/Database.php b/src/Database.php index 1aee3d8..bd16445 100644 --- a/src/Database.php +++ b/src/Database.php @@ -4,6 +4,8 @@ namespace Krutush\Database; class Database{ private $pdo; + private $debug = false; + private $requests = []; public function __construct(array $settings){ $dns = $settings['driver'] . @@ -12,6 +14,7 @@ class Database{ ';dbname=' . $settings['schema'] . ((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']); } @@ -20,6 +23,9 @@ class Database{ } public function prepare(string $request){ + if($this->debug) + $this->requests[] = $request; + return $this->pdo->prepare($request); } @@ -72,8 +78,12 @@ class Database{ return $drop; } - public function getLastInsertId(){ + public function getLastInsertId(): int{ return $this->pdo->lastInsertId(); } + + public function getRequests(): array{ + return $this->requests; + } //TODO update, delete } \ No newline at end of file diff --git a/src/Model.php b/src/Model.php index b3e5efd..2a11136 100644 --- a/src/Model.php +++ b/src/Model.php @@ -14,9 +14,15 @@ class Model{ /** @var string */ public const TABLE = null; - /** @var array - * @example ['id' => ['column' => 'idColumn', 'type' => 'int', 'not_null' => true, 'primary' => true, 'custom' => 'AUTO_INCREMENT']] */ + /** @var array */ 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 * @example ['id' => ['value' => 1, 'modified' => false]] */ @@ -127,6 +133,10 @@ class Model{ 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{ $fields = static::getFields(); $columns = []; @@ -172,11 +182,19 @@ class Model{ public function getModifiedValues(){ $values = []; foreach ($this->fields as $field => $data) { - if($data['modified']) $values[] = $data['value']; + if($data['modified']) + $values[] = $data['value']; + } return $values; } + public function unmodify(){ + foreach($this->fields as $field => $data){ + $this->fields[$field]['modified'] = false; + } + } + public function getPrimaryValues(){ $values = []; foreach ($this->fields as $field => $data) { @@ -207,6 +225,15 @@ class Model{ case 'bit': $data = boolval($data); //MAYBE: E_NOTICE on strange types 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: throw new DatabaseException('unknown type in field : '.$field); break; @@ -244,8 +271,13 @@ class Model{ return $req; } - public function runInsert(){ - return static::insert()->run($this->getValues()); + public function runInsert(bool $forceID = true){ + $insert = static::insert(); + $res = $insert->run($this->getValues()); + if($forceID) + $this->{static::ID} = Connection::get(static::DATABASE)->getLastInsertID(); + + return $res; } public function runUpdate(){ @@ -253,7 +285,9 @@ class Model{ ->update(static::getModifiedColumns()) ->table(static::TABLE) ->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{ @@ -261,14 +295,42 @@ class Model{ ->create(static::TABLE); foreach (static::getFields() as $field => $options) { + $column = static::getColumn($field); $req->column( - static::getColumn($field), + $column, $options['type'], isset($options['lenght']) ? $options['lenght'] : null, isset($options['not_null']) && $options['not_null'], - isset($options['primary']) && $options['primary'], - isset($options['unique']) && $options['unique'], 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; @@ -325,13 +387,11 @@ class Model{ return $data['count']; } - - /* TODO: Manager ids - public static function find($id) { + public static function find($id): ?self{ 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().' = ?')); - }*/ + } } \ No newline at end of file diff --git a/src/Request/Create.php b/src/Request/Create.php index 44593a8..d12ae7f 100644 --- a/src/Request/Create.php +++ b/src/Request/Create.php @@ -10,19 +10,49 @@ class Create extends Request{ protected $columns = []; protected $primary = []; protected $unique = []; + protected $index = []; + protected $foreign = []; public function table(string $table): Create{ $this->table = $table; 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 : ''); - if($primary) - $this->primary[] = '`'.$name.'`'; + return $this; + } - if($unique) - $this->unique[$name] = [$name]; + public function primary(string $name): Create{ + $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; } @@ -35,7 +65,19 @@ class Create extends Request{ $uniques = []; 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". @@ -43,9 +85,11 @@ class Create extends Request{ array_merge( $this->columns, (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)"; } diff --git a/src/Request/Request.php b/src/Request/Request.php index 5e793cf..f778b56 100644 --- a/src/Request/Request.php +++ b/src/Request/Request.php @@ -4,7 +4,7 @@ namespace Krutush\Database\Request; use Krutush\Database\Database; -class Request{ +class Request{ //TODO: escape and slugify protected $db; public function __construct(Database $db){