Foreign, debug, datetime and ids

This commit is contained in:
sheychen 2018-05-13 13:43:45 +02:00
parent 365f2ff580
commit 4fb305a1c2
4 changed files with 138 additions and 24 deletions

View File

@ -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
}

View File

@ -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().' = ?'));
}*/
}
}

View File

@ -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)";
}

View File

@ -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){